home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / C and C++ / GNU Chess 3.0 / Sources TC 4.0 / gnuchess.c < prev    next >
Text File  |  1991-04-23  |  75KB  |  3,262 lines

  1. /*
  2.   C source for GNU CHESS
  3.  
  4.   Modified : 20-3-91 Airy ANDRE.
  5.  
  6.   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
  7.   Copyright (c) 1988, 1989, 1990  John Stanback
  8.   Copyright (c) 1991 Airy André
  9.  
  10.   This file is part of CHESS.
  11.  
  12.   CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
  13.   WARRANTY.  No author or distributor accepts responsibility to anyone for
  14.   the consequences of using it or for whether it serves any particular
  15.   purpose or works at all, unless he says so in writing.  Refer to the CHESS
  16.   General Public License for full details.
  17.  
  18.   Everyone is granted permission to copy, modify and redistribute CHESS, but
  19.   only under the conditions described in the CHESS General Public License. A
  20.   copy of this license is supposed to have been given to you along with
  21.   CHESS so you can know your rights and responsibilities.  It should be in a
  22.   file named COPYING.  Among other things, the copyright notice and this
  23.   notice must be preserved on all copies.
  24. */
  25.  
  26. /* This file is the original "gnuchess.c" modified to allow a Mac interface
  27.    and a few new options.
  28.    It is for Mac version ONLY
  29.    --------------------------
  30. */
  31.  
  32. #include <stdio.h>
  33.  
  34. extern int fprintf ();
  35. extern int fflush ();
  36.  
  37. #include <ctype.h>
  38.  
  39. /*
  40.   ttblsz must be a power of 2.
  41.   Setting ttblsz 0 removes the transposition tables.
  42. */
  43. #include <time.h>
  44. #define ttblsz 65536
  45. #define huge
  46.  
  47. extern int abs ();
  48. extern int atoi ();
  49.  
  50. extern void *memset(void *, int, size_t);
  51.  
  52. #include "gnuchess.h"
  53.  
  54. #define bpawn 7
  55. #define valueP 100
  56. #define valueN 350
  57. #define valueB 355
  58. #define valueR 550
  59. #define valueQ 1100
  60. #define valueK 1200
  61. #define ctlP 0x4000
  62. #define ctlN 0x2800
  63. #define ctlB 0x1800
  64. #define ctlR 0x0400
  65. #define ctlQ 0x0200
  66. #define ctlK 0x0100
  67. #define ctlBQ 0x1200
  68. #define ctlRQ 0x0600
  69. #define ctlNN 0x2000
  70.  
  71.  
  72. #if ttblsz
  73. #define truescore 0x0001
  74. #define lowerbound 0x0002
  75. #define upperbound 0x0004
  76. #define kingcastle 0x0008
  77. #define queencastle 0x0010
  78.  
  79. struct hashval
  80. {
  81.   unsigned long key,bd;
  82. };
  83.  
  84. struct hashentry
  85. {
  86.   unsigned long hashbd;
  87.   unsigned short mv;
  88.   unsigned char flags, depth;    /* char saves some space */
  89.   short score;
  90. #ifdef HASHTEST
  91.   unsigned char bd[32];
  92. #endif /* HASHTEST */
  93. };
  94.  
  95. #ifdef HASHFILE
  96. /*
  97.   persistent transposition table.
  98.   The size must be a power of 2. If you change the size,
  99.   be sure to run gnuchess -t before anything else.
  100. */
  101. #define frehash 6
  102. #define filesz 131072
  103. struct fileentry
  104. {
  105.   unsigned char bd[32];
  106.   unsigned char f, t, flags, depth, sh, sl;
  107. };
  108. /*
  109.   In a networked enviroment gnuchess might be compiled on different
  110.   hosts with different random number generators, that is not acceptable
  111.   if they are going to share the same transposition table.
  112. */
  113. unsigned long int next = 1;
  114.  
  115. unsigned int rand()
  116. {
  117.   next *= 1103515245;
  118.   next += 12345;
  119.   return ((unsigned int) (next >> 16) & 0xFFFF);
  120. }
  121.  
  122. void srand (seed)
  123.      unsigned int seed;
  124. {
  125.   next = seed;
  126. }
  127.  
  128. #endif /* HASHFILE */
  129.  
  130. static unsigned long hashkey, hashbd;
  131. static struct hashval *hashcode[2][7];
  132. static struct hashentry huge *ttable[2];
  133. #endif /* ttblsz */
  134.  
  135. int hashfile;
  136. struct leaf *Tree, *root;
  137. short TrPnt[maxdepth];
  138. short PieceList[2][16], PawnCnt[2][8];
  139. short castld[2], Mvboard[64];
  140. short c1, c2, *atk1, *atk2, *PC1, *PC2, atak[2][64];
  141. short mate, post, opponent, computer, Sdepth, Awindow, Bwindow, dither;
  142. long ResponseTime, ExtraTime, Level[2], et, et0, ft;
  143. unsigned long time0;
  144. long NodeCnt, ETnodes, EvalNodes, HashCnt, FHashCnt, HashCol;
  145. short quit, reverse, bothsides, hashflag, InChk, player, force, easy, beep;
  146. short timeout, xwndw, rehash;
  147. struct GameRec *GameList;
  148. short GameCnt, Game50, epsquare, lpost, rcptr, contempt;
  149. short MaxSearchDepth;
  150. struct BookEntry *Book;
  151. struct TimeControlRec TimeControl;
  152. short TCflag[2], TCmoves[2], TCminutes[2], OperatorTime[2];
  153.  
  154. short donotplay;
  155.  
  156. #ifdef ttblsz
  157. static unsigned long real_ttblsz = ttblsz;
  158. #endif /* ttblsz */
  159.  
  160. const short otherside[3] =
  161. {1, 0, 2};
  162. unsigned short hint, PrVar[maxdepth];
  163.  
  164. static short Pindex[64], svalue[64];
  165. static short PieceCnt[2];
  166. static short mtl[2], pmtl[2], emtl[2], hung[2];
  167. static short EnemyKing;
  168. static short wking, bking, FROMsquare, TOsquare, Zscore, zwndw, slk;
  169. static short INCscore;
  170. static short HasPawn[2], HasKnight[2], HasBishop[2], HasRook[2], HasQueen[2];
  171. static short ChkFlag[maxdepth], CptrFlag[maxdepth], PawnThreat[maxdepth];
  172. static short Pscore[maxdepth], Tscore[maxdepth];
  173. static const short qrook[3] =
  174. {0, 56, 0};
  175. static const short krook[3] =
  176. {7, 63, 0};
  177. static const short kingP[3] =
  178. {4, 60, 0};
  179. static const short rank7[3] =
  180. {6, 1, 0};
  181. static const short sweep[7] =
  182. {false, false, false, true, true, true, false};
  183. static unsigned short *killr0, *killr1, *killr2;
  184. static unsigned short *killr3;
  185. static unsigned short PV, Swag0, Swag1, Swag2, Swag3, Swag4;
  186. static unsigned char *history;
  187.  
  188. static short *Mwpawn, *Mbpawn, *Mknight[2], *Mbishop[2];
  189. static short *Mking[2], *Kfield[2];
  190. static const short value[7] =
  191. {0, valueP, valueN, valueB, valueR, valueQ, valueK};
  192. static const short control[7] =
  193. {0, ctlP, ctlN, ctlB, ctlR, ctlQ, ctlK};
  194. static const short PassedPawn0[8] =
  195. {0, 60, 80, 120, 200, 360, 600, 800};
  196. static const short PassedPawn1[8] =
  197. {0, 30, 40, 60, 100, 180, 300, 800};
  198. static const short PassedPawn2[8] =
  199. {0, 15, 25, 35, 50, 90, 140, 800};
  200. static const short PassedPawn3[8] =
  201. {0, 5, 10, 15, 20, 30, 140, 800};
  202. static const short ISOLANI[8] =
  203. {-12, -16, -20, -24, -24, -20, -16, -12};
  204. static const short BACKWARD[16] =
  205. {-6, -10, -15, -21, -28, -28, -28, -28,
  206.  -28, -28, -28, -28, -28, -28, -28, -28};
  207. static const short BMBLTY[14] =
  208. {-2, 0, 2, 4, 6, 8, 10, 12, 13, 14, 15, 16, 16, 16};
  209. static const short RMBLTY[15] =
  210. {0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14};
  211. static const short KTHRT[36] =
  212. {0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
  213.  -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
  214.  -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80};
  215. static short KNIGHTPOST, KNIGHTSTRONG, BISHOPSTRONG, KATAK, KBNKsq;
  216. static short PEDRNK2B, PWEAKH, PADVNCM, PADVNCI, PAWNSHIELD, PDOUBLED, PBLOK;
  217. static short RHOPN, RHOPNX, KHOPN, KHOPNX, KSFTY;
  218. static short ATAKD, HUNGP, HUNGX, KCASTLD, KMOVD, XRAY, PINVAL;
  219. static short stage, stage2, Zwmtl, Zbmtl, Developed[2], PawnStorm;
  220. static short PawnBonus, BishopBonus, RookBonus;
  221. static const short KingOpening[64] =
  222. {0, 0, -4, -10, -10, -4, 0, 0,
  223.  -4, -4, -8, -12, -12, -8, -4, -4,
  224.  -12, -16, -20, -20, -20, -20, -16, -12,
  225.  -16, -20, -24, -24, -24, -24, -20, -16,
  226.  -16, -20, -24, -24, -24, -24, -20, -16,
  227.  -12, -16, -20, -20, -20, -20, -16, -12,
  228.  -4, -4, -8, -12, -12, -8, -4, -4,
  229.  0, 0, -4, -10, -10, -4, 0, 0};
  230. static const short KingEnding[64] =
  231. {0, 6, 12, 18, 18, 12, 6, 0,
  232.  6, 12, 18, 24, 24, 18, 12, 6,
  233.  12, 18, 24, 30, 30, 24, 18, 12,
  234.  18, 24, 30, 36, 36, 30, 24, 18,
  235.  18, 24, 30, 36, 36, 30, 24, 18,
  236.  12, 18, 24, 30, 30, 24, 18, 12,
  237.  6, 12, 18, 24, 24, 18, 12, 6,
  238.  0, 6, 12, 18, 18, 12, 6, 0};
  239. static const short DyingKing[64] =
  240. {0, 8, 16, 24, 24, 16, 8, 0,
  241.  8, 32, 40, 48, 48, 40, 32, 8,
  242.  16, 40, 56, 64, 64, 56, 40, 16,
  243.  24, 48, 64, 72, 72, 64, 48, 24,
  244.  24, 48, 64, 72, 72, 64, 48, 24,
  245.  16, 40, 56, 64, 64, 56, 40, 16,
  246.  8, 32, 40, 48, 48, 40, 32, 8,
  247.  0, 8, 16, 24, 24, 16, 8, 0};
  248. static const short KBNK[64] =
  249. {99, 90, 80, 70, 60, 50, 40, 40,
  250.  90, 80, 60, 50, 40, 30, 20, 40,
  251.  80, 60, 40, 30, 20, 10, 30, 50,
  252.  70, 50, 30, 10, 0, 20, 40, 60,
  253.  60, 40, 20, 0, 10, 30, 50, 70,
  254.  50, 30, 10, 20, 30, 40, 60, 80,
  255.  40, 20, 30, 40, 50, 60, 80, 90,
  256.  40, 40, 50, 60, 70, 80, 90, 99};
  257. static const short pknight[64] =
  258. {0, 4, 8, 10, 10, 8, 4, 0,
  259.  4, 8, 16, 20, 20, 16, 8, 4,
  260.  8, 16, 24, 28, 28, 24, 16, 8,
  261.  10, 20, 28, 32, 32, 28, 20, 10,
  262.  10, 20, 28, 32, 32, 28, 20, 10,
  263.  8, 16, 24, 28, 28, 24, 16, 8,
  264.  4, 8, 16, 20, 20, 16, 8, 4,
  265.  0, 4, 8, 10, 10, 8, 4, 0};
  266. static const short pbishop[64] =
  267. {14, 14, 14, 14, 14, 14, 14, 14,
  268.  14, 22, 18, 18, 18, 18, 22, 14,
  269.  14, 18, 22, 22, 22, 22, 18, 14,
  270.  14, 18, 22, 22, 22, 22, 18, 14,
  271.  14, 18, 22, 22, 22, 22, 18, 14,
  272.  14, 18, 22, 22, 22, 22, 18, 14,
  273.  14, 22, 18, 18, 18, 18, 22, 14,
  274.  14, 14, 14, 14, 14, 14, 14, 14};
  275. static const short PawnAdvance[64] =
  276. {0, 0, 0, 0, 0, 0, 0, 0,
  277.  4, 4, 4, 0, 0, 4, 4, 4,
  278.  6, 8, 2, 10, 10, 2, 8, 6,
  279.  6, 8, 12, 16, 16, 12, 8, 6,
  280.  8, 12, 16, 24, 24, 16, 12, 8,
  281.  12, 16, 24, 32, 32, 24, 16, 12,
  282.  12, 16, 24, 32, 32, 24, 16, 12,
  283.  0, 0, 0, 0, 0, 0, 0, 0};
  284.  
  285.  
  286. /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
  287.  
  288.  
  289. #define taxicab(a,b) taxidata[a][b]
  290. short *distdata[64], *taxidata[64];
  291.  
  292. inline void
  293. Initialize_dist (void)
  294. {
  295.   register short a, b, d, di;
  296.  
  297.   for (a = 0; a < 64; a++)
  298.     for (b = 0; b < 64; b++)
  299.       {
  300.     d = abs (column (a) - column (b));
  301.     di = abs (row (a) - row (b));
  302.     taxidata[a][b] = d + di;
  303.     distdata[a][b] = (d > di ? d : di);
  304.       }
  305. }
  306.  
  307. const short Stboard[64] =
  308. {rook, knight, bishop, queen, king, bishop, knight, rook,
  309.  pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  310.  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  311.  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  312.  pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  313.  rook, knight, bishop, queen, king, bishop, knight, rook};
  314. const short Stcolor[64] =
  315. {white, white, white, white, white, white, white, white,
  316.  white, white, white, white, white, white, white, white,
  317.  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  318.  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  319.  black, black, black, black, black, black, black, black,
  320.  black, black, black, black, black, black, black, black};
  321. short board[64], color[64];
  322. static unsigned char *nextpos[8][64];
  323. static unsigned char *nextdir[8][64];
  324. /*
  325.   ptype is used to separate white and black pawns, like this;
  326.   ptyp = ptype[side][piece]
  327.   piece can be used directly in nextpos/nextdir when generating moves
  328.   for pieces that are not black pawns.
  329. */
  330. static const short ptype[2][8] =
  331. {
  332.   no_piece, pawn, knight, bishop, rook, queen, king, no_piece,
  333.   no_piece, bpawn, knight, bishop, rook, queen, king, no_piece};
  334. static const short direc[8][8] =
  335. {
  336.   0, 0, 0, 0, 0, 0, 0, 0,
  337.   10, 9, 11, 0, 0, 0, 0, 0,
  338.   8, -8, 12, -12, 19, -19, 21, -21,
  339.   9, 11, -9, -11, 0, 0, 0, 0,
  340.   1, 10, -1, -10, 0, 0, 0, 0,
  341.   1, 10, -1, -10, 9, 11, -9, -11,
  342.   1, 10, -1, -10, 9, 11, -9, -11,
  343.   -10, -9, -11, 0, 0, 0, 0, 0};
  344. static const short max_steps[8] =
  345. {0, 2, 1, 7, 7, 7, 1, 2};
  346. static const short nunmap[120] =
  347. {
  348.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  349.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  350.   -1, 0, 1, 2, 3, 4, 5, 6, 7, -1,
  351.   -1, 8, 9, 10, 11, 12, 13, 14, 15, -1,
  352.   -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
  353.   -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
  354.   -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
  355.   -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
  356.   -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
  357.   -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
  358.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  359.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
  360.  
  361.  
  362. #ifdef HASHFILE
  363.  
  364. /* 
  365.    Check if hashfile exists. If it doesn't, ask if a new one have to be
  366.    created
  367. */
  368.  
  369. int CheckHashFile(void)
  370. {
  371.   if (FSOpen (HASHFILE, 0, &hashfile) == fnfErr)
  372.   {
  373.           if (!AreYouSure(_NEWTABLE_STR)) return 0;
  374.           Create(HASHFILE, 0, 'GCHS', 'GCht');
  375.          if (FSOpen (HASHFILE, 0, &hashfile) != noErr)
  376.           {
  377.               ShowError(_CREATE_STR);
  378.               hashfile = 0;
  379.               return 0;
  380.           }
  381.         if (hashfile != 0)
  382.         {
  383.             long i, j;
  384.             struct fileentry n;
  385.             long count;
  386.             
  387.             for(j = 0; j < 32; j++)
  388.               n.bd[j] = 0;
  389.             n.f = n.t = 0;
  390.             n.flags = 0;
  391.             n.depth = 0;
  392.             n.sh = n.sl = 0;
  393.             for (j = 0; j < filesz; j++) {
  394.               long count = sizeof(struct fileentry);
  395.               if (FSWrite(hashfile, &count, &n) != noErr) {
  396.                   ShowError(_WRITE_STR);
  397.                   FSClose(hashfile);
  398.                   FSDelete(HASHFILE, 0);
  399.                   hashfile = 0;
  400.                   return 0;
  401.               }
  402.             }
  403.         }
  404.     }
  405.     return 1;
  406. }
  407. #endif
  408.  
  409. static void alloc_tables()
  410. {
  411.     int i,j;
  412.     
  413. #if ttblsz
  414.     void *reserved;
  415.     
  416.     for (i=0; i<2; i++)
  417.         for (j=0; j<7; j++) {
  418.             hashcode[i][j] = (struct hashval*)NewPtr(64*sizeof(struct hashval));
  419.             if (hashcode[i][j] == NULL)
  420.                 ExitToShell();
  421.     }
  422.     
  423.     reserved = NewPtr(200000);
  424.     
  425.     if (reserved == NULL) ExitToShell();
  426.     while (real_ttblsz) {
  427.         ttable[0] = (struct hashentry*)NewPtr(real_ttblsz*sizeof(struct hashentry));
  428.         if (ttable[0] == NULL) {
  429.             real_ttblsz >>= 1;
  430.             continue;
  431.         }
  432.         ttable[1] = (struct hashentry*)NewPtr(real_ttblsz*sizeof(struct hashentry));
  433.         if (ttable[1] == NULL) {
  434.             DisposPtr(ttable[0]);
  435.             real_ttblsz >>= 1;
  436.             continue;
  437.         }
  438.         break;
  439.     }
  440.     DisposPtr(reserved);
  441.     if (real_ttblsz == 0) ExitToShell();
  442.     
  443. #endif /* ttblsz */
  444.  
  445.     killr0 = (unsigned short *)NewPtr(maxdepth*sizeof(unsigned short ));
  446.     killr1 = (unsigned short *)NewPtr(maxdepth*sizeof(unsigned short ));
  447.     killr2 = (unsigned short *)NewPtr(maxdepth*sizeof(unsigned short ));
  448.     killr3 = (unsigned short *)NewPtr(maxdepth*sizeof(unsigned short ));
  449.     history = (unsigned char*)NewPtr(8192 * sizeof(unsigned char));
  450.  
  451.     Mwpawn = (short *)NewPtr(64*sizeof(short ));
  452.     Mbpawn = (short *)NewPtr(64*sizeof(short ));
  453.     Mknight[0] = (short *)NewPtr(64*sizeof(short ));
  454.     Mknight[1] = (short *)NewPtr(64*sizeof(short ));
  455.     Mking[0] = (short *)NewPtr(64*sizeof(short ));
  456.     Mking[1] = (short *)NewPtr(64*sizeof(short ));
  457.     Mbishop[0] = (short *)NewPtr(64*sizeof(short ));
  458.     Mbishop[1] = (short *)NewPtr(64*sizeof(short ));
  459.     Kfield[0] = (short *)NewPtr(64*sizeof(short ));
  460.     Kfield[1] = (short *)NewPtr(64*sizeof(short ));
  461.     
  462.     GameList = (struct GameRec*)NewPtr(500 * sizeof(struct GameRec));
  463.     for (i=0; i<64; i++) {
  464.         distdata[i] = (short*)NewPtr(64*sizeof(short));
  465.         taxidata[i] = (short*)NewPtr(64*sizeof(short));
  466.     }
  467.     for (i=0; i<8; i++)
  468.         for (j=0; j<64; j++) {
  469.             nextpos[i][j] = (unsigned char *)NewPtr(64L);
  470.             nextdir[i][j] = (unsigned char *)NewPtr(64L);
  471.         }
  472.         
  473.     root = Tree = (struct leaf *)NewPtr(2000*sizeof(struct leaf));
  474.  
  475. }
  476.  
  477. void
  478. Initialize_moves ()
  479.  
  480. /*
  481.   This procedure pre-calculates all moves for every piece from every square.
  482.   This data is stored in nextpos/nextdir and used later in the move generation
  483.   routines.
  484. */
  485.  
  486. {
  487.   short ptyp, po, p0, d, di, s, delta;
  488.   unsigned char *ppos, *pdir;
  489.   short dest[8][8];
  490.   short steps[8];
  491.   short sorted[8];
  492.  
  493.   for (ptyp = 0; ptyp < 8; ptyp++)
  494.     for (po = 0; po < 64; po++)
  495.       for (p0 = 0; p0 < 64; p0++)
  496.     {
  497.       nextpos[ptyp][po][p0] = po;
  498.       nextdir[ptyp][po][p0] = po;
  499.     }
  500.   for (ptyp = 1; ptyp < 8; ptyp++)
  501.     for (po = 21; po < 99; po++)
  502.       if (nunmap[po] >= 0)
  503.     {
  504.       ppos = nextpos[ptyp][nunmap[po]];
  505.       pdir = nextdir[ptyp][nunmap[po]];
  506.       /* dest is a function of direction and steps */
  507.       for (d = 0; d < 8; d++)
  508.         {
  509.           dest[d][0] = nunmap[po];
  510.           delta = direc[ptyp][d];
  511.           if (delta != 0)
  512.         {
  513.           p0 = po;
  514.           for (s = 0; s < max_steps[ptyp]; s++)
  515.             {
  516.               p0 = p0 + delta;
  517.               /*
  518.             break if (off board) or
  519.             (pawns only move two steps from home square)
  520.               */
  521.               if (nunmap[p0] < 0 || (ptyp == pawn || ptyp == bpawn)
  522.               && s > 0 && (d > 0 || Stboard[nunmap[po]] != pawn))
  523.             break;
  524.               else
  525.             dest[d][s] = nunmap[p0];
  526.             }
  527.         }
  528.           else
  529.         s = 0;
  530.  
  531.           /*
  532.             sort dest in number of steps order
  533.             currently no sort is done due to compability with
  534.             the move generation order in old gnu chess
  535.           */
  536.           steps[d] = s;
  537.           for (di = d; s > 0 && di > 0; di--)
  538.         if (steps[sorted[di - 1]] == 0)    /* should be: < s */
  539.           sorted[di] = sorted[di - 1];
  540.         else
  541.           break;
  542.           sorted[di] = d;
  543.         }
  544.  
  545.       /*
  546.         update nextpos/nextdir,
  547.         pawns have two threads (capture and no capture)
  548.       */
  549.       p0 = nunmap[po];
  550.       if (ptyp == pawn || ptyp == bpawn)
  551.         {
  552.           for (s = 0; s < steps[0]; s++)
  553.         {
  554.           ppos[p0] = dest[0][s];
  555.           p0 = dest[0][s];
  556.         }
  557.           p0 = nunmap[po];
  558.           for (d = 1; d < 3; d++)
  559.         {
  560.           pdir[p0] = dest[d][0];
  561.           p0 = dest[d][0];
  562.         }
  563.         }
  564.       else
  565.         {
  566.           pdir[p0] = dest[sorted[0]][0];
  567.           for (d = 0; d < 8; d++)
  568.         for (s = 0; s < steps[sorted[d]]; s++)
  569.           {
  570.             ppos[p0] = dest[sorted[d]][s];
  571.             p0 = dest[sorted[d]][s];
  572.             if (d < 7)
  573.               pdir[p0] = dest[sorted[d + 1]][0];
  574.             /* else is already initialized */
  575.           }
  576.         }
  577.     }
  578. }
  579.  
  580. /* Dispose memory allocated for the Opening Book */
  581. void DisposBook()
  582. {
  583.     struct BookEntry *p;
  584.     
  585.     while (Book != NULL) {
  586.         p = Book;
  587.         Book = Book->next;
  588.         free(p->mv);
  589.         free(p);
  590.     }
  591. }
  592.  
  593. void
  594. NewGame ()
  595. /*
  596.   Reset the board and other variables to start a new game.
  597. */
  598. {
  599.   short l, c, p;
  600.  
  601.   stage = stage2 = -1;        /* the game is not yet started */
  602.   mate = quit = false;
  603.   PawnStorm = false;
  604.   beep = rcptr = true; 
  605.   
  606.   NodeCnt = et0 = epsquare = lpost = 0;
  607.   dither = 0;
  608.   Awindow = 90;
  609.   Bwindow = 90;
  610.   xwndw = 90;
  611.   MaxSearchDepth = 29;
  612.   contempt = 0;
  613.   GameCnt = -1;
  614.   Game50 = 0;
  615.   Zwmtl = Zbmtl = 0;
  616.   Developed[white] = Developed[black] = false;
  617.   castld[white] = castld[black] = false;
  618.   PawnThreat[0] = CptrFlag[0] = false;
  619.   Pscore[0] = 12000;
  620.   Tscore[0] = 12000;
  621.  
  622.   for (l = 0; l < 2000; l++)
  623.     Tree[l].f = Tree[l].t = 0;
  624. #if ttblsz
  625.   rehash = 6;
  626.   ZeroTTable ();
  627.   srand ((unsigned int) 1);
  628.   for (c = white; c <= black; c++)
  629.     for (p = pawn; p <= king; p++)
  630.       for (l = 0; l < 64; l++)
  631.     {
  632.       hashcode[c][p][l].key = (((unsigned long) rand ()));
  633.       hashcode[c][p][l].key += (((unsigned long) rand ()) << 16);
  634.       hashcode[c][p][l].bd = (((unsigned long) rand ()));
  635.       hashcode[c][p][l].bd += (((unsigned long) rand ()) << 16);
  636.       if (sizeof(long) > 4)
  637.         {
  638.           hashcode[c][p][l].key += (((unsigned long) rand ()) << 32);
  639.           hashcode[c][p][l].key += (((unsigned long) rand ()) << 48);
  640.           hashcode[c][p][l].bd += (((unsigned long) rand ()) << 32);
  641.           hashcode[c][p][l].bd += (((unsigned long) rand ()) << 48);
  642.         }
  643.     }
  644. #endif /* ttblsz */
  645.   for (l = 0; l < 64; l++)
  646.     {
  647.       board[l] = Stboard[l];
  648.       color[l] = Stcolor[l];
  649.       Mvboard[l] = 0;
  650.     }
  651.   if (TCflag[white]) SetTimeControl (white);
  652.   if (TCflag[black]) SetTimeControl (black);
  653.  
  654.   InitializeStats ();
  655.   DisposBook();
  656.   GetOpenings ();
  657.   time0 = Ticks;
  658.   ElapsedTime (1);
  659. }
  660.  
  661.  
  662. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  663.  
  664. inline void
  665. pick (p1, p2)
  666.      short int p1;
  667.      register short int p2;
  668.  
  669. /*
  670.   Find the best move in the tree between indexes p1 and p2. Swap the best
  671.   move into the p1 element.
  672. */
  673.  
  674. {
  675.   register short p, s;
  676.   register short p0, s0;
  677.   struct leaf temp;
  678.  
  679.   s0 = Tree[p1].score;
  680.   p0 = p1;
  681.   for (p = p1 + 1; p <= p2; p++)
  682.     if ((s = Tree[p].score) > s0)
  683.       {
  684.     s0 = s;
  685.     p0 = p;
  686.       }
  687.   if (p0 != p1)
  688.     {
  689.       temp = Tree[p1];
  690.       Tree[p1] = Tree[p0];
  691.       Tree[p0] = temp;
  692.     }
  693. }
  694.  
  695. void
  696. SelectMove (side, iop)
  697.      short int side;
  698.      short int iop;
  699. /*
  700.   Select a move by calling function search() at progressively deeper ply
  701.   until time is up or a mate or draw is reached. An alpha-beta window of -90
  702.   to +90 points is set around the score returned from the previous
  703.   iteration. If Sdepth != 0 then the program has correctly predicted the
  704.   opponents move and the search will start at a depth of Sdepth+1 rather
  705.   than a depth of 1.
  706. */
  707. {
  708.   static alpha, beta, score, tempb, tempc, tempsf, tempst, xside, rpt;
  709.   register short i;
  710.   
  711.   timeout = false;
  712.   xside = otherside[side];
  713.   if (iop != 2)
  714.     player = side;
  715.   if (TCflag[side])
  716.     {
  717.       if ((TimeControl.moves[side] + 3) != 0)
  718.     ResponseTime = (TimeControl.clock[side]) /
  719.       (TimeControl.moves[side] + 3) -
  720.       OperatorTime[side];
  721.       else
  722.     ResponseTime = 0;
  723.       ResponseTime += (ResponseTime * TimeControl.moves[side]) / (2 * TCmoves[side] + 1);
  724.     }
  725.   else
  726.     ResponseTime = Level[side];
  727.   if (iop == 2)
  728.     ResponseTime = 99999;
  729.   if (Sdepth > 0 && root->score > Zscore - zwndw)
  730.     ResponseTime -= ft;
  731.   else if (ResponseTime < 1)
  732.     ResponseTime = 1;
  733.   ExtraTime = 0;
  734.   ExaminePosition ();
  735.   ScorePosition (side, &score);
  736.   /* Pscore[0] = -score; */
  737.  
  738.   if (Sdepth == 0)
  739.     {
  740. #if ttblsz
  741.       /* ZeroTTable (); */
  742. #endif /* ttblsz */
  743.       SearchStartStuff (side);
  744. #ifdef NOMEMSET
  745.       for (i = 0; i < 8192; i++)
  746.     history[i] = 0;
  747. #else
  748.       memset ((char *) history, 0, sizeof (history));
  749. #endif /* NOMEMSET */
  750.       FROMsquare = TOsquare = -1;
  751.       PV = 0;
  752.       if (iop != 2)
  753.         hint = 0;
  754.       for (i = 0; i < maxdepth; i++)
  755.         PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  756.       alpha = score - 90;
  757.       beta = score + 90;
  758.       rpt = 0;
  759.       TrPnt[1] = 0;
  760.       root = &Tree[0];
  761.       MoveList (side, 1);
  762.       for (i = TrPnt[1]; i < TrPnt[2]; i++)
  763.         pick (i, TrPnt[2] - 1);
  764.       if (Book != NULL)
  765.             OpeningBook ();
  766.       if (Book != NULL)
  767.             timeout = true;
  768.       NodeCnt = ETnodes = EvalNodes = HashCnt = FHashCnt = HashCol = 0;
  769.       Zscore = 0;
  770.       zwndw = 20;
  771.     }
  772.     while (!timeout && Sdepth < MaxSearchDepth)
  773.     {
  774.       Sdepth++;
  775.       score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  776.       for (i = 1; i <= Sdepth; i++)
  777.         killr0[i] = PrVar[i];
  778.       if (score < alpha)
  779.     {
  780.       ExtraTime = 10 * ResponseTime;
  781.       /* ZeroTTable (); */
  782.       score = search (side, 1, Sdepth, -9000, score, PrVar, &rpt);
  783.     }
  784.       if (score > beta && !(root->flags & exact))
  785.     {
  786.       ExtraTime = 0;
  787.       /* ZeroTTable (); */
  788.       score = search (side, 1, Sdepth, score, 9000, PrVar, &rpt);
  789.     }
  790.       score = root->score;
  791.       if (!timeout)
  792.     for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
  793.       pick (i, TrPnt[2] - 1);
  794.       ShowResults (score, PrVar, '.');
  795.       for (i = 1; i <= Sdepth; i++)
  796.         killr0[i] = PrVar[i];
  797.     if (score > Zscore - zwndw && score > Tree[1].score + 250)
  798.         ExtraTime = 0;
  799.       else if (score > Zscore - 3 * zwndw)
  800.     ExtraTime = ResponseTime;
  801.       else
  802.     ExtraTime = 3 * ResponseTime;
  803.       if (root->flags & exact)
  804.     timeout = true;
  805.       if (Tree[1].score < -9000)
  806.     timeout = true;
  807.       if (4 * et > 2 * ResponseTime + ExtraTime)
  808.     timeout = true;
  809.       if (!timeout)
  810.         {
  811.           Tscore[0] = score;
  812.     
  813.           Zscore = Zscore?(Zscore + score) / 2:score;
  814.         }
  815.       zwndw = 20 + abs (Zscore / 12);
  816.       beta = score + Bwindow;
  817.       if (Zscore < score)
  818.     alpha = Zscore - Awindow - zwndw;
  819.       else
  820.     alpha = score - Awindow - zwndw;
  821.     }
  822.  
  823.   if (donotplay) return;
  824.  
  825.   score = root->score;
  826.   if (rpt >= 2 || score < -12000)
  827.     root->flags |= draw;
  828.   if (iop == 2)
  829.     return;
  830.  
  831.   ElapsedTime (1);
  832.   if (Book == NULL)
  833.     hint = PrVar[2];
  834.  
  835.   if (score > -9999 && rpt <= 2)
  836.     {
  837.       MakeMove (side, root, &tempb, &tempc, &tempsf, &tempst);
  838.       algbr (root->f, root->t, (short) root->flags);
  839.     }
  840.   else
  841.     algbr (0, 0, 0);
  842.     
  843.   if (score == -9999 || score == 9998)
  844.     mate = true;
  845.   if (mate)
  846.     hint = 0;
  847.   if (root->flags & cstlmask)
  848.     Game50 = GameCnt;
  849.   else if (board[root->t] == pawn || (root->flags & capture))
  850.     Game50 = GameCnt;
  851.   GameList[GameCnt].score = score;
  852.   GameList[GameCnt].nodes = NodeCnt;
  853.   GameList[GameCnt].time = (short) et;
  854.   GameList[GameCnt].depth = Sdepth;
  855.   if (TCflag[side])
  856.     {
  857.       TimeControl.clock[side] -= (et + OperatorTime[side]);
  858.       if (--TimeControl.moves[side] == 0)
  859.                     SetTimeControl (side);
  860.     }
  861.   if ((root->flags & draw) && bothsides)
  862.     mate = true;
  863.   if (GameCnt > 498)
  864.     mate = true; /* out of move store, you loose */
  865.   player = xside;
  866.   Sdepth = 0;
  867.  
  868.   OutputMove ();
  869.   return;
  870. }
  871.  
  872. void
  873. OpeningBook ()
  874. /*
  875.   Go thru each of the opening lines of play and check for a match with the
  876.   current game listing. If a match occurs, generate a random number. If this
  877.   number is the largest generated so far then the next move in this line
  878.   becomes the current "candidate". After all lines are checked, the
  879.   candidate move is put at the top of the Tree[] array and will be played by
  880.   the program. Note that the program does not handle book transpositions.
  881. */
  882. {
  883.   short j, pnt;
  884.   unsigned short m, *mp;
  885.   unsigned r, r0;
  886.   struct BookEntry *p;
  887.  
  888.   srand ((unsigned int) time0);
  889.   r0 = m = 0;
  890.   p = Book;
  891.   while (p != NULL)
  892.     {
  893.       mp = p->mv;
  894.       for (j = 0; j <= GameCnt; j++)
  895.     if (GameList[j].gmove != *(mp++))
  896.       break;
  897.       if (j > GameCnt)
  898.     if ((r = rand ()) > r0)
  899.       {
  900.         r0 = r;
  901.         m = *mp;
  902.         hint = *(++mp);
  903.       }
  904.       p = p->next;
  905.     }
  906.  
  907.   for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
  908.     if (((Tree[pnt].f << 8) | Tree[pnt].t) == m)
  909.       Tree[pnt].score = 0;
  910.   pick (TrPnt[1], TrPnt[2] - 1);
  911.   if (Tree[TrPnt[1]].score < 0)
  912.     DisposBook();
  913. }
  914.  
  915.  
  916. inline void
  917. repetition (cnt)
  918.      short int *cnt;
  919.  
  920. /*
  921.   Check for draw by threefold repetition.
  922. */
  923.  
  924. {
  925.   register short i, c, f, t;
  926.   short b[64];
  927.   unsigned short m;
  928.  
  929.   *cnt = c = 0;
  930.   if (GameCnt > Game50 + 3)
  931.     {
  932. #ifdef NOMEMSET
  933.       for (i = 0; i < 64; b[i++] = 0) ;
  934. #else
  935.       memset ((char *) b, 0, sizeof (b));
  936. #endif /* NOMEMSET */
  937.       for (i = GameCnt; i > Game50; i--)
  938.     {
  939.       m = GameList[i].gmove;
  940.       f = m >> 8;
  941.       t = m & 0xFF;
  942.       if (++b[f] == 0)
  943.         c--;
  944.       else
  945.         c++;
  946.       if (--b[t] == 0)
  947.         c--;
  948.       else
  949.         c++;
  950.       if (c == 0)
  951.         (*cnt)++;
  952.     }
  953.     }
  954. }
  955.  
  956. int
  957. search (side, ply, depth, alpha, beta, bstline, rpt)
  958.      short int side;
  959.      short int ply;
  960.      short int depth;
  961.      short int alpha;
  962.      short int beta;
  963.      short unsigned int *bstline;
  964.      short int *rpt;
  965.  
  966. /*
  967.   Perform an alpha-beta search to determine the score for the current board
  968.   position. If depth <= 0 only capturing moves, pawn promotions and
  969.   responses to check are generated and searched, otherwise all moves are
  970.   processed. The search depth is modified for check evasions, certain
  971.   re-captures and threats. Extensions may continue for up to 11 ply beyond
  972.   the nominal search depth.
  973. */
  974.  
  975. #define UpdateSearchStatus \
  976. {\
  977.    if (post) ShowCurrentMove(pnt,node->f,node->t);\
  978.      if (pnt > TrPnt[1])\
  979.        {\
  980.       d = best-Zscore; e = best-node->score;\
  981.         if (best < alpha) ExtraTime = 10*ResponseTime;\
  982.         else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
  983.         else if (d > -zwndw) ExtraTime = 0;\
  984.         else if (d > -3*zwndw) ExtraTime = ResponseTime;\
  985.         else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
  986.         else ExtraTime = 5*ResponseTime;\
  987.         }\
  988.         }
  989. #define prune (cf && score+node->score < alpha)
  990. #define ReCapture (rcptr && score > alpha && score < beta &&\
  991.            ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
  992.             /* && depth == Sdepth-ply+1 */
  993. #define Parry (hung[side] > 1 && ply == Sdepth+1)
  994. #define MateThreat (ply < Sdepth+4 && ply > 4 &&\
  995.             ChkFlag[ply-2] && ChkFlag[ply-4] &&\
  996.             ChkFlag[ply-2] != ChkFlag[ply-4])
  997.  
  998. {
  999.   register short j, pnt;
  1000.   short best, tempb, tempc, tempsf, tempst;
  1001.   short xside, pbst, d, e, cf, score, rcnt;
  1002.   unsigned short mv, nxtline[maxdepth];
  1003.   struct leaf *node, tmp;
  1004.  
  1005.   NodeCnt++;
  1006.   xside = otherside[side];
  1007.  
  1008.   /* could this be removed ? */
  1009.   if (depth < 0)
  1010.     depth = 0;
  1011.  
  1012.   if (ply <= Sdepth + 3)
  1013.     repetition (rpt);
  1014.   else
  1015.     *rpt = 0;
  1016.   /* Detect repetitions a bit earlier. SMC. 12/89 */
  1017.   if (*rpt == 1 && ply > 1)
  1018.     return (0);
  1019.   /* if (*rpt >= 2) return(0); */
  1020.  
  1021.   score = evaluate (side, xside, ply, alpha, beta);
  1022.   if (score > 9000)
  1023.     {
  1024.       bstline[ply] = 0;
  1025.       return (score);
  1026.     }
  1027.   if (depth > 0)
  1028.     {
  1029.       /* Allow opponent a chance to check again */
  1030.       if (InChk) {
  1031.         if (depth < 2) depth = 2;
  1032.     }
  1033.       else if (PawnThreat[ply - 1] || ReCapture)
  1034.     ++depth;
  1035.     }
  1036.   else
  1037.     {
  1038.       if (score >= alpha &&
  1039.       (InChk || PawnThreat[ply - 1] || Parry))
  1040.     depth = 1;
  1041.       else if (score <= beta && MateThreat)
  1042.     depth = 1;
  1043.     }
  1044.  
  1045. #if ttblsz
  1046.   if (depth > 0 && hashflag && ply > 1)
  1047.     {
  1048.       if (ProbeTTable (side, depth, &alpha, &beta, &score) == false)
  1049. #ifdef HASHFILE    
  1050.     if ((depth > 4) && (GameCnt < 12) && hashfile)
  1051.       ProbeFTable (side, depth, &alpha, &beta, &score);
  1052. #else
  1053.       /* do nothing */;
  1054. #endif /* HASHFILE */      
  1055.       bstline[ply] = PV;
  1056.       bstline[ply + 1] = 0;
  1057.       if (beta == -20000)
  1058.     return (score);
  1059.       if (alpha > beta)
  1060.     return (alpha);
  1061.     }
  1062. #endif /* ttblsz */
  1063.   d = (Sdepth == 1)?7:11;
  1064.   if (ply > Sdepth + d || (depth < 1 && score > beta))
  1065.     /* score >= beta ?? */
  1066.     return (score);
  1067.  
  1068.   if (ply > 1)
  1069.     if (depth > 0)
  1070.       MoveList (side, ply);
  1071.     else
  1072.       CaptureList (side, xside, ply);
  1073.  
  1074.   if (TrPnt[ply] == TrPnt[ply + 1])
  1075.     return (score);
  1076.  
  1077.   cf = (depth < 1 && ply > Sdepth + 1 && !ChkFlag[ply - 2] && !slk);
  1078.  
  1079.   if (depth > 0)
  1080.     best = -12000;
  1081.   else
  1082.     best = score;
  1083.   if (best > alpha)
  1084.     alpha = best;
  1085.  
  1086.   for (pnt = pbst = TrPnt[ply];
  1087.        pnt < TrPnt[ply + 1] && best <= beta;    /* best < beta ?? */
  1088.        pnt++)
  1089.     {
  1090.       if (ply > 1)
  1091.     pick (pnt, TrPnt[ply + 1] - 1);
  1092.       node = &Tree[pnt];
  1093.       mv = (node->f << 8) | node->t;
  1094.       nxtline[ply + 1] = 0;
  1095.  
  1096.       if (prune)
  1097.     break;
  1098.       if (ply == 1)
  1099.     UpdateSearchStatus;
  1100.  
  1101.       if (!(node->flags & exact))
  1102.     {
  1103.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1104.       CptrFlag[ply] = (node->flags & capture);
  1105.       PawnThreat[ply] = (node->flags & pwnthrt);
  1106.       Tscore[ply] = node->score;
  1107.       PV = node->reply;
  1108.       node->score = -search (xside, ply + 1, depth - 1, -beta, -alpha,
  1109.                  nxtline, &rcnt);
  1110.       if (abs (node->score) > 9000)
  1111.         node->flags |= exact;
  1112.       else if (rcnt == 1)
  1113.         node->score /= 2;
  1114.       if (rcnt >= 2 || GameCnt - Game50 > 99 ||
  1115.           (node->score == 9999 - ply && !ChkFlag[ply]))
  1116.         {
  1117.           node->flags |= draw;
  1118.           node->flags |= exact;
  1119.           if (side == computer)
  1120.         node->score = contempt;
  1121.           else
  1122.         node->score = -contempt;
  1123.         }
  1124.       node->reply = nxtline[ply + 1];
  1125.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1126.     }
  1127.       if (node->score > best && !timeout)
  1128.     {
  1129.       if (depth > 0)
  1130.         if (node->score > alpha && !(node->flags & exact))
  1131.           node->score += depth;
  1132.       best = node->score;
  1133.       pbst = pnt;
  1134.       if (best > alpha)
  1135.         alpha = best;
  1136.       for (j = ply + 1; nxtline[j] > 0; j++)
  1137.         bstline[j] = nxtline[j];
  1138.       bstline[j] = 0;
  1139.       bstline[ply] = mv;
  1140.       if (ply == 1)
  1141.         {
  1142.           if (best > root->score)
  1143.         {
  1144.           tmp = Tree[pnt];
  1145.           for (j = pnt - 1; j >= 0; j--)
  1146.             Tree[j + 1] = Tree[j];
  1147.           Tree[0] = tmp;
  1148.           pbst = 0;
  1149.         }
  1150.           if (Sdepth > 4)
  1151.         if (best > beta)
  1152.           ShowResults (best, bstline, '+');
  1153.         else if (best < alpha)
  1154.           ShowResults (best, bstline, '-');
  1155.         else
  1156.           ShowResults (best, bstline, '&');
  1157.         }
  1158.     }
  1159.       if (NodeCnt > ETnodes)
  1160.     ElapsedTime (0);
  1161.       if (timeout)
  1162.     return (-Tscore[ply - 1]);
  1163.     }
  1164.  
  1165.   node = &Tree[pbst];
  1166.   mv = (node->f << 8) | node->t;
  1167. #if ttblsz
  1168.   if (hashflag && ply <= Sdepth && *rpt == 0 && best == alpha)
  1169.     {
  1170.       PutInTTable (side, best, depth, alpha, beta, mv);
  1171. #ifdef HASHFILE      
  1172.       if ((depth > 4) && (GameCnt < 12) && hashfile)
  1173.     PutInFTable (side, best, depth, alpha, beta, node->f, node->t);
  1174. #endif /* HASHFILE */      
  1175.     }
  1176. #endif /* ttblsz */
  1177.   if (depth > 0)
  1178.     {
  1179.       j = (node->f << 6) | node->t;
  1180.       if (side == black)
  1181.     j |= 0x1000;
  1182.       if (history[j] < 150)
  1183.     history[j] += 2 * depth;
  1184.       if (node->t != (GameList[GameCnt].gmove & 0xFF))
  1185.     if (best <= beta)
  1186.       killr3[ply] = mv;
  1187.     else if (mv != killr1[ply])
  1188.       {
  1189.         killr2[ply] = killr1[ply];
  1190.         killr1[ply] = mv;
  1191.       }
  1192.       if (best > 9000)
  1193.     killr0[ply] = mv;
  1194.       else
  1195.     killr0[ply] = 0;
  1196.     }
  1197.   return (best);
  1198. }
  1199.  
  1200. #if ttblsz
  1201. #define CB(i) ((color[2 * (i)] ? 0x80 : 0)\
  1202.            | (board[2 * (i)] << 4)\
  1203.            | (color[2 * (i) + 1] ? 0x8 : 0)\
  1204.            | (board[2 * (i) + 1]))
  1205.  
  1206. int
  1207. ProbeTTable (side, depth, alpha, beta, score)
  1208.      short int side;
  1209.      short int depth;
  1210.      short int *alpha;
  1211.      short int *beta;
  1212.      short int *score;
  1213.  
  1214. /*
  1215.   Look for the current board position in the transposition table.
  1216. */
  1217.  
  1218. {
  1219.   register struct hashentry *ptbl;
  1220.   register unsigned short i;
  1221.  
  1222.   ptbl = &ttable[side][hashkey & (real_ttblsz - 1)];
  1223.  
  1224.   /* rehash max rehash times */
  1225.   for (i = 1; ptbl->hashbd != hashbd && i <= rehash; i++)
  1226.     ptbl = &ttable[side][(hashkey + i) & (real_ttblsz - 1)];
  1227.   if (ptbl->depth >= depth && ptbl->hashbd == hashbd)
  1228.     {
  1229.       HashCnt++;
  1230. #ifdef HASHTEST
  1231.       for (i = 0; i < 32; i++)
  1232.     {
  1233.       if (ptbl->bd[i] != CB(i))
  1234.         {
  1235.           HashCol++;
  1236.           break;
  1237.         }
  1238.     }
  1239. #endif /* HASHTEST */
  1240.  
  1241.       PV = ptbl->mv;
  1242.       if (ptbl->flags & truescore)
  1243.     {
  1244.       *score = ptbl->score;
  1245.       *beta = -20000;
  1246.     }
  1247. #if 0 /* commented out, why? */
  1248.       else if (ptbl->flags & upperbound)
  1249.     {
  1250.       if (ptbl->score < *beta) *beta = ptbl->score+1;
  1251.     }
  1252. #endif
  1253.       else if (ptbl->flags & lowerbound)
  1254.     {
  1255.       if (ptbl->score > *alpha)
  1256.         *alpha = ptbl->score - 1;
  1257.     }
  1258.       return(true);
  1259.     }
  1260.   return(false);
  1261. }
  1262.  
  1263. void
  1264. PutInTTable (side, score, depth, alpha, beta, mv)
  1265.      short int side;
  1266.      short int score;
  1267.      short int depth;
  1268.      short int alpha;
  1269.      short int beta;
  1270.      short unsigned int mv;
  1271.  
  1272. /*
  1273.   Store the current board position in the transposition table.
  1274. */
  1275.  
  1276. {
  1277.   register struct hashentry *ptbl;
  1278.   register unsigned short i;
  1279.  
  1280.   ptbl = &ttable[side][hashkey & (real_ttblsz - 1)];
  1281.  
  1282.   /* rehash max rehash times */
  1283.   for (i = 1; depth < ptbl->depth && ptbl->hashbd != hashbd && i <= rehash; i++)
  1284.     ptbl = &ttable[side][(hashkey + i) & (real_ttblsz - 1)];
  1285.   if (depth > ptbl->depth || ptbl->hashbd != hashbd)
  1286.     {
  1287.       ptbl->hashbd = hashbd;
  1288.       ptbl->depth = depth;
  1289.       ptbl->score = score;
  1290.       ptbl->mv = mv;
  1291.       ptbl->flags = 0;
  1292.       if (score < alpha)
  1293.     ptbl->flags |= upperbound;
  1294.       else if (score > beta)
  1295.     ptbl->flags |= lowerbound;
  1296.       else
  1297.     ptbl->flags |= truescore;
  1298. #ifdef HASHTEST
  1299.       for (i = 0; i < 32; i++)
  1300.     {
  1301.       ptbl->bd[i] = CB(i);
  1302.     }
  1303. #endif /* HASHTEST */
  1304.     }
  1305. }
  1306.  
  1307. void
  1308. ZeroTTable ()
  1309. {
  1310.   register unsigned long side, i;
  1311.  
  1312.   if (hashflag)
  1313.     for (side = 0; side < 2; side++)
  1314.       for (i = 0; i < real_ttblsz; i++)
  1315.         ttable[side][i].depth = 0;
  1316. }
  1317.  
  1318. #ifdef HASHFILE
  1319. int
  1320. ProbeFTable(side, depth, alpha, beta, score)
  1321.      short int side;
  1322.      short int depth;
  1323.      short int *alpha;
  1324.      short int *beta;
  1325.      short int *score;
  1326.  
  1327. /*
  1328.   Look for the current board position in the persistent transposition table.
  1329. */
  1330.  
  1331. {
  1332.   register unsigned short i, j;
  1333.   register unsigned long hashix;
  1334.   short s;
  1335.   struct fileentry new, t;
  1336.  
  1337.   if (side == white)
  1338.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  1339.   else
  1340.     hashix = hashkey | 1 & (filesz - 1);
  1341.  
  1342.   for (i = 0; i < 32; i++)
  1343.     new.bd[i] = CB(i);
  1344.   new.flags = 0;
  1345.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  1346.     new.flags |= queencastle;
  1347.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  1348.     new.flags |= kingcastle;
  1349.  
  1350.   for (i = 0; i < frehash; i++)
  1351.     {
  1352.       long count;
  1353.       
  1354.       SetFPos(hashfile,
  1355.         fsFromStart,
  1356.         sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1))
  1357.         );
  1358.       count = sizeof(struct fileentry);
  1359.       FSRead(hashfile, &count, &t);
  1360.       for (j = 0; j < 32; j++)
  1361.     if (t.bd[j] != new.bd[j])
  1362.       break;
  1363.       if ((t.depth >= depth) && (j >= 32)
  1364.       && (new.flags == (t.flags & (kingcastle | queencastle))))
  1365.     {
  1366.       FHashCnt++;
  1367.       PV = (t.f << 8) | t.t;
  1368.       s = (t.sh << 8) | t.sl;
  1369.       if (t.flags & truescore)
  1370.         {
  1371.           *score = s;
  1372.           *beta = -20000;
  1373.         }
  1374.       else if (t.flags & lowerbound)
  1375.         {
  1376.           if (s > *alpha)
  1377.         *alpha = s - 1;
  1378.         }
  1379.       return(true);
  1380.     }
  1381.     }
  1382.   return(false);
  1383. }
  1384.  
  1385. void
  1386. PutInFTable (side, score, depth, alpha, beta, f, t)
  1387.      short int side;
  1388.      short int score;
  1389.      short int depth;
  1390.      short int alpha;
  1391.      short int beta;
  1392.      short unsigned int f;
  1393.      short unsigned int t;
  1394.  
  1395. /*
  1396.   Store the current board position in the persistent transposition table.
  1397. */
  1398.  
  1399. {
  1400.   register unsigned short i;
  1401.   register unsigned long hashix;
  1402.   struct fileentry new, tmp;
  1403.  
  1404.   if (side == white)
  1405.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  1406.   else
  1407.     hashix = hashkey | 1 & (filesz - 1);
  1408.  
  1409.   for (i = 0; i < 32; i++)
  1410.     new.bd[i] = CB(i);
  1411.   new.f = f;
  1412.   new.t = t;
  1413.   new.flags = 0;
  1414.   if (score < alpha)
  1415.     new.flags |= upperbound;
  1416.   else if (score > beta)
  1417.     new.flags |= lowerbound;
  1418.   else
  1419.     new.flags |= truescore;
  1420.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  1421.     new.flags |= queencastle;
  1422.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  1423.     new.flags |= kingcastle;
  1424.   new.depth = depth;
  1425.   new.sh = score >> 8;
  1426.   new.sl = score & 0xFF;
  1427.  
  1428.   for (i = 0; i < frehash; i++)
  1429.     {
  1430.       long count;
  1431.       
  1432.       SetFPos(hashfile,
  1433.           fsFromStart,
  1434.         sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1))
  1435.         );
  1436.       count = sizeof(struct fileentry);
  1437.       FSRead(hashfile, &count, &tmp);
  1438.        if (tmp.depth <= depth)
  1439.     {
  1440.       SetFPos(hashfile,
  1441.           fsFromStart,
  1442.         sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1))
  1443.         );
  1444.       count = sizeof(struct fileentry);
  1445.       FSWrite(hashfile, &count, &new);
  1446.       break;
  1447.     }
  1448.  
  1449.     }
  1450. }
  1451. #endif /* HASHFILE */
  1452. #endif /* ttblsz */
  1453.  
  1454. #define Link(from,to,flag,s) \
  1455. {\
  1456.    node->f = from; node->t = to;\
  1457.    node->reply = 0;\
  1458.    node->flags = flag;\
  1459.    node->score = s;\
  1460.    ++node;\
  1461.    ++TrPnt[ply+1];\
  1462. }
  1463.  
  1464. inline void
  1465. LinkMove (ply, f, t, flag, xside)
  1466.      short int ply;
  1467.      short int f;
  1468.      short int t;
  1469.      short int flag;
  1470.      short int xside;
  1471.  
  1472. /*
  1473.   Add a move to the tree.  Assign a bonus to order the moves
  1474.   as follows:
  1475.   1. Principle variation
  1476.   2. Capture of last moved piece
  1477.   3. Other captures (major pieces first)
  1478.   4. Killer moves
  1479.   5. "history" killers
  1480. */
  1481.  
  1482. {
  1483.   register short s, z;
  1484.   register unsigned short mv;
  1485.   register struct leaf *node;
  1486.  
  1487.   node = &Tree[TrPnt[ply + 1]];
  1488.   mv = (f << 8) | t;
  1489.   s = 0;
  1490.   if (mv == Swag0)
  1491.     s = 2000;
  1492.   else if (mv == Swag1)
  1493.     s = 60;
  1494.   else if (mv == Swag2)
  1495.     s = 50;
  1496.   else if (mv == Swag3)
  1497.     s = 40;
  1498.   else if (mv == Swag4)
  1499.     s = 30;
  1500.   z = (f << 6) | t;
  1501.   if (xside == white)
  1502.     z |= 0x1000;
  1503.   s += history[z];
  1504.   if (color[t] != neutral)
  1505.     {
  1506.       flag |= capture;
  1507.       if (t == TOsquare)
  1508.     s += 500;
  1509.       s += value[board[t]] - board[f];
  1510.     }
  1511.   if (board[f] == pawn)
  1512.     if (row (t) == 0 || row (t) == 7)
  1513.       {
  1514.     flag |= promote;
  1515.     s += 800;
  1516.     Link (f, t, flag | queen, s - 20000);
  1517.     s -= 200;
  1518.     Link (f, t, flag | knight, s - 20000);
  1519.     s -= 50;
  1520.     Link (f, t, flag | rook, s - 20000);
  1521.     flag |= bishop;
  1522.     s -= 50;
  1523.       }
  1524.     else if (row (t) == 1 || row (t) == 6)
  1525.       {
  1526.     flag |= pwnthrt;
  1527.     s += 600;
  1528.       }
  1529.     else if (t == epsquare)
  1530.       flag |= epmask;
  1531.   Link (f, t, flag, s - 20000);
  1532. }
  1533.  
  1534.  
  1535. inline void
  1536. GenMoves (ply, sq, side, xside)
  1537.      short int ply;
  1538.      short int sq;
  1539.      short int side;
  1540.      short int xside;
  1541.  
  1542. /*
  1543.   Generate moves for a piece. The moves are taken from the precalulated
  1544.   array nextpos/nextdir. If the board is free, next move is choosen from
  1545.   nextpos else from nextdir.
  1546. */
  1547.  
  1548. {
  1549.   register short u, piece;
  1550.   register unsigned char *ppos, *pdir;
  1551.  
  1552.   piece = board[sq];
  1553.   ppos = nextpos[ptype[side][piece]][sq];
  1554.   pdir = nextdir[ptype[side][piece]][sq];
  1555.   if (piece == pawn)
  1556.     {
  1557.       u = ppos[sq];    /* follow no captures thread */
  1558.       if (color[u] == neutral)
  1559.     {
  1560.       LinkMove (ply, sq, u, 0, xside);
  1561.       u = ppos[u];
  1562.       if (color[u] == neutral)
  1563.         LinkMove (ply, sq, u, 0, xside);
  1564.     }
  1565.       u = pdir[sq];    /* follow captures thread */
  1566.       if (color[u] == xside || u == epsquare)
  1567.     LinkMove (ply, sq, u, capture, xside);
  1568.       u = pdir[u];
  1569.       if (color[u] == xside || u == epsquare)
  1570.     LinkMove (ply, sq, u, capture, xside);
  1571.     }
  1572.   else
  1573.     {
  1574.       u = ppos[sq];
  1575.       do
  1576.     {
  1577.       if (color[u] == neutral)
  1578.         {
  1579.           LinkMove (ply, sq, u, 0, xside);
  1580.           u = ppos[u];
  1581.         }
  1582.       else
  1583.         {
  1584.           if (color[u] == xside)
  1585.         LinkMove (ply, sq, u, capture, xside);
  1586.           u = pdir[u];
  1587.         }
  1588.       } while (u != sq);
  1589.     }
  1590. }
  1591.  
  1592. void
  1593. MoveList (side, ply)
  1594.      short int side;
  1595.      short int ply;
  1596.  
  1597. /*
  1598.   Fill the array Tree[] with all available moves for side to play. Array
  1599.   TrPnt[ply] contains the index into Tree[] of the first move at a ply.
  1600. */
  1601.  
  1602. {
  1603.   register short i, xside, f;
  1604.  
  1605.   xside = otherside[side];
  1606.   TrPnt[ply + 1] = TrPnt[ply];
  1607.   if (PV == 0)
  1608.     Swag0 = killr0[ply];
  1609.   else
  1610.     Swag0 = PV;
  1611.   Swag1 = killr1[ply];
  1612.   Swag2 = killr2[ply];
  1613.   Swag3 = killr3[ply];
  1614.   Swag4 = 0;
  1615.   if (ply > 2)
  1616.     Swag4 = killr1[ply - 2];
  1617.   for (i = PieceCnt[side]; i >= 0; i--)
  1618.     GenMoves (ply, PieceList[side][i], side, xside);
  1619.   if (!castld[side])
  1620.     {
  1621.       f = PieceList[side][0];
  1622.       if (castle (side, f, f + 2, 0))
  1623.     {
  1624.       LinkMove (ply, f, f + 2, cstlmask, xside);
  1625.     }
  1626.       if (castle (side, f, f - 2, 0))
  1627.     {
  1628.       LinkMove (ply, f, f - 2, cstlmask, xside);
  1629.     }
  1630.     }
  1631. }
  1632.  
  1633. void
  1634. CaptureList (side, xside, ply)
  1635.      short int side;
  1636.      short int xside;
  1637.      short int ply;
  1638.  
  1639. /*
  1640.   Fill the array Tree[] with all available cature and promote moves for
  1641.   side to play. Array TrPnt[ply] contains the index into Tree[]
  1642.   of the first move at a ply.
  1643. */
  1644.  
  1645. {
  1646.   register short u, sq;
  1647.   register unsigned char *ppos, *pdir;
  1648.   short i, piece, *PL, r7;
  1649.   struct leaf *node;
  1650.  
  1651.   TrPnt[ply + 1] = TrPnt[ply];
  1652.   node = &Tree[TrPnt[ply]];
  1653.   r7 = rank7[side];
  1654.   PL = PieceList[side];
  1655.   for (i = 0; i <= PieceCnt[side]; i++)
  1656.     {
  1657.       sq = PL[i];
  1658.       piece = board[sq];
  1659.       if (sweep[piece])
  1660.     {
  1661.       ppos = nextpos[piece][sq];
  1662.       pdir = nextdir[piece][sq];
  1663.       u = ppos[sq];
  1664.       do
  1665.         {
  1666.           if (color[u] == neutral)
  1667.         u = ppos[u];
  1668.           else
  1669.         {
  1670.           if (color[u] == xside)
  1671.             Link (sq, u, capture,
  1672.               value[board[u]] + svalue[board[u]] - piece);
  1673.           u = pdir[u];
  1674.         }
  1675.       } while (u != sq);
  1676.     }
  1677.       else
  1678.     {
  1679.       pdir = nextdir[ptype[side][piece]][sq];
  1680.       if (piece == pawn && row (sq) == r7)
  1681.         {
  1682.           u = pdir[sq];
  1683.           if (color[u] == xside)
  1684.         Link (sq, u, capture | promote | queen, valueQ);
  1685.           u = pdir[u];
  1686.           if (color[u] == xside)
  1687.         Link (sq, u, capture | promote | queen, valueQ);
  1688.           ppos = nextpos[ptype[side][piece]][sq];
  1689.           u = ppos[sq]; /* also generate non capture promote */
  1690.           if (color[u] == neutral)
  1691.         Link (sq, u, promote | queen, valueQ);
  1692.         }
  1693.       else
  1694.         {
  1695.           u = pdir[sq];
  1696.           do
  1697.         {
  1698.           if (color[u] == xside)
  1699.             Link (sq, u, capture,
  1700.               value[board[u]] + svalue[board[u]] - piece);
  1701.           u = pdir[u];
  1702.           } while (u != sq);
  1703.         }
  1704.     }
  1705.     }
  1706. }
  1707.  
  1708.  
  1709. int
  1710. castle (side, kf, kt, iop)
  1711.      short int side;
  1712.      short int kf;
  1713.      short int kt;
  1714.      short int iop;
  1715.  
  1716. /* Make or Unmake a castling move. */
  1717.  
  1718. {
  1719.   register short rf, rt, t0, xside;
  1720.  
  1721.   xside = otherside[side];
  1722.   if (kt > kf)
  1723.     {
  1724.       rf = kf + 3;
  1725.       rt = kt - 1;
  1726.     }
  1727.   else
  1728.     {
  1729.       rf = kf - 4;
  1730.       rt = kt + 1;
  1731.     }
  1732.   if (iop == 0)
  1733.     {
  1734.       if (kf != kingP[side] ||
  1735.       board[kf] != king ||
  1736.       board[rf] != rook ||
  1737.       Mvboard[kf] != 0 ||
  1738.       Mvboard[rf] != 0 ||
  1739.       color[kt] != neutral ||
  1740.       color[rt] != neutral ||
  1741.       color[kt - 1] != neutral ||
  1742.       SqAtakd (kf, xside) ||
  1743.       SqAtakd (kt, xside) ||
  1744.       SqAtakd (rt, xside))
  1745.     return (false);
  1746.  
  1747.     }
  1748.   else
  1749.     {
  1750.       if (iop == 1)
  1751.     {
  1752.       castld[side] = true;
  1753.       Mvboard[kf]++;
  1754.       Mvboard[rf]++;
  1755.     }
  1756.       else
  1757.     {
  1758.       castld[side] = false;
  1759.       Mvboard[kf]--;
  1760.       Mvboard[rf]--;
  1761.       t0 = kt;
  1762.       kt = kf;
  1763.       kf = t0;
  1764.       t0 = rt;
  1765.       rt = rf;
  1766.       rf = t0;
  1767.     }
  1768.       board[kt] = king;
  1769.       color[kt] = side;
  1770.       Pindex[kt] = 0;
  1771.       board[kf] = no_piece;
  1772.       color[kf] = neutral;
  1773.       board[rt] = rook;
  1774.       color[rt] = side;
  1775.       Pindex[rt] = Pindex[rf];
  1776.       board[rf] = no_piece;
  1777.       color[rf] = neutral;
  1778.       PieceList[side][Pindex[kt]] = kt;
  1779.       PieceList[side][Pindex[rt]] = rt;
  1780. #if ttblsz
  1781.       if (hashflag)
  1782.     {
  1783.       UpdateHashbd (side, king, kf, kt);
  1784.       UpdateHashbd (side, rook, rf, rt);
  1785.     }
  1786. #endif /* ttblsz */
  1787.     }
  1788.   return (true);
  1789. }
  1790.  
  1791.  
  1792. inline void
  1793. EnPassant (xside, f, t, iop)
  1794.      short int xside;
  1795.      short int f;
  1796.      short int t;
  1797.      short int iop;
  1798.  
  1799. /*
  1800.   Make or unmake an en passant move.
  1801. */
  1802.  
  1803. {
  1804.   register short l;
  1805.  
  1806.   if (t > f)
  1807.     l = t - 8;
  1808.   else
  1809.     l = t + 8;
  1810.   if (iop == 1)
  1811.     {
  1812.       board[l] = no_piece;
  1813.       color[l] = neutral;
  1814.     }
  1815.   else
  1816.     {
  1817.       board[l] = pawn;
  1818.       color[l] = xside;
  1819.     }
  1820.   InitializeStats ();
  1821. }
  1822.  
  1823.  
  1824. inline void
  1825. UpdatePieceList (side, sq, iop)
  1826.      short int side;
  1827.      short int sq;
  1828.      short int iop;
  1829.  
  1830. /*
  1831.   Update the PieceList and Pindex arrays when a piece is captured or when a
  1832.   capture is unmade.
  1833. */
  1834.  
  1835. {
  1836.   register short i;
  1837.   if (iop == 1)
  1838.     {
  1839.       PieceCnt[side]--;
  1840.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1841.     {
  1842.       PieceList[side][i] = PieceList[side][i + 1];
  1843.       Pindex[PieceList[side][i]] = i;
  1844.     }
  1845.     }
  1846.   else
  1847.     {
  1848.       PieceCnt[side]++;
  1849.       PieceList[side][PieceCnt[side]] = sq;
  1850.       Pindex[sq] = PieceCnt[side];
  1851.     }
  1852. }
  1853.  
  1854. void
  1855. MakeMove (side, node, tempb, tempc, tempsf, tempst)
  1856.      short int side;
  1857.      struct leaf *node;
  1858.      short int *tempb;
  1859.      short int *tempc;
  1860.      short int *tempsf;
  1861.      short int *tempst;
  1862.  
  1863. /*
  1864.   Update Arrays board[], color[], and Pindex[] to reflect the new board
  1865.   position obtained after making the move pointed to by node. Also update
  1866.   miscellaneous stuff that changes when a move is made.
  1867. */
  1868.  
  1869. {
  1870.   register short f, t, xside, ct, cf;
  1871.  
  1872.   xside = otherside[side];
  1873.   f = node->f;
  1874.   t = node->t;
  1875.   epsquare = -1;
  1876.   FROMsquare = f;
  1877.   TOsquare = t;
  1878.   INCscore = 0;
  1879.   GameList[++GameCnt].gmove = (f << 8) | t;
  1880.  
  1881.   if (node->flags & cstlmask)
  1882.     {
  1883.       GameList[GameCnt].piece = no_piece;
  1884.       GameList[GameCnt].color = side;
  1885.       (void) castle (side, f, t, 1);
  1886.     }
  1887.   else
  1888.     {
  1889.       *tempc = color[t];
  1890.       *tempb = board[t];
  1891.       *tempsf = svalue[f];
  1892.       *tempst = svalue[t];
  1893.       GameList[GameCnt].piece = *tempb;
  1894.       GameList[GameCnt].color = *tempc;
  1895.       if (*tempc != neutral)
  1896.     {
  1897.       UpdatePieceList (*tempc, t, 1);
  1898.       if (*tempb == pawn)
  1899.         --PawnCnt[*tempc][column (t)];
  1900.       if (board[f] == pawn)
  1901.         {
  1902.           --PawnCnt[side][column (f)];
  1903.           ++PawnCnt[side][column (t)];
  1904.           cf = column (f);
  1905.           ct = column (t);
  1906.           if (PawnCnt[side][ct] > 1 + PawnCnt[side][cf])
  1907.         INCscore -= 15;
  1908.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1909.         INCscore += 15;
  1910.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1911.         INCscore -= 15;
  1912.         }
  1913.       mtl[xside] -= value[*tempb];
  1914.       if (*tempb == pawn)
  1915.         pmtl[xside] -= valueP;
  1916. #if ttblsz
  1917.       if (hashflag)
  1918.         UpdateHashbd (xside, *tempb, -1, t);
  1919. #endif /* ttblsz */
  1920.       INCscore += *tempst;
  1921.       Mvboard[t]++;
  1922.     }
  1923.       color[t] = color[f];
  1924.       board[t] = board[f];
  1925.       svalue[t] = svalue[f];
  1926.       Pindex[t] = Pindex[f];
  1927.       PieceList[side][Pindex[t]] = t;
  1928.       color[f] = neutral;
  1929.       board[f] = no_piece;
  1930.       if (board[t] == pawn)
  1931.     if (t - f == 16)
  1932.       epsquare = f + 8;
  1933.     else if (f - t == 16)
  1934.       epsquare = f - 8;
  1935.       if (node->flags & promote)
  1936.     {
  1937.       board[t] = node->flags & pmask;
  1938.       if (board[t] == queen)
  1939.         HasQueen[side]++;
  1940.       else if (board[t] == rook)
  1941.         HasRook[side]++;
  1942.       else if (board[t] == bishop)
  1943.         HasBishop[side]++;
  1944.       else if (board[t] == knight)
  1945.         HasKnight[side]++;
  1946.       --PawnCnt[side][column (t)];
  1947.       mtl[side] += value[board[t]] - valueP;
  1948.       pmtl[side] -= valueP;
  1949. #if ttblsz
  1950.       if (hashflag)
  1951.         {
  1952.           UpdateHashbd (side, pawn, f, -1);
  1953.           UpdateHashbd (side, board[t], f, -1);
  1954.         }
  1955. #endif /* ttblsz */
  1956.       INCscore -= *tempsf;
  1957.     }
  1958.       if (node->flags & epmask)
  1959.     EnPassant (xside, f, t, 1);
  1960.       else
  1961. #if ttblsz
  1962.       if (hashflag)
  1963.     UpdateHashbd (side, board[t], f, t);
  1964. #endif /* ttblsz */
  1965.       Mvboard[f]++;
  1966.     }
  1967. }
  1968.  
  1969. void
  1970. UnmakeMove (side, node, tempb, tempc, tempsf, tempst)
  1971.      short int side;
  1972.      struct leaf *node;
  1973.      short int *tempb;
  1974.      short int *tempc;
  1975.      short int *tempsf;
  1976.      short int *tempst;
  1977.  
  1978. /*
  1979.   Take back a move.
  1980. */
  1981.  
  1982. {
  1983.   register short f, t, xside;
  1984.  
  1985.   xside = otherside[side];
  1986.   f = node->f;
  1987.   t = node->t;
  1988.   epsquare = -1;
  1989.   GameCnt--;
  1990.   if (node->flags & cstlmask)
  1991.     (void) castle (side, f, t, 2);
  1992.   else
  1993.     {
  1994.       color[f] = color[t];
  1995.       board[f] = board[t];
  1996.       svalue[f] = *tempsf;
  1997.       Pindex[f] = Pindex[t];
  1998.       PieceList[side][Pindex[f]] = f;
  1999.       color[t] = *tempc;
  2000.       board[t] = *tempb;
  2001.       svalue[t] = *tempst;
  2002.       if (node->flags & promote)
  2003.     {
  2004.       board[f] = pawn;
  2005.       ++PawnCnt[side][column (t)];
  2006.       mtl[side] += valueP - value[node->flags & pmask];
  2007.       pmtl[side] += valueP;
  2008. #if ttblsz
  2009.       if (hashflag)
  2010.         {
  2011.           UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  2012.           UpdateHashbd (side, pawn, -1, t);
  2013.         }
  2014. #endif /* ttblsz */
  2015.     }
  2016.       if (*tempc != neutral)
  2017.     {
  2018.       UpdatePieceList (*tempc, t, 2);
  2019.       if (*tempb == pawn)
  2020.         ++PawnCnt[*tempc][column (t)];
  2021.       if (board[f] == pawn)
  2022.         {
  2023.           --PawnCnt[side][column (t)];
  2024.           ++PawnCnt[side][column (f)];
  2025.         }
  2026.       mtl[xside] += value[*tempb];
  2027.       if (*tempb == pawn)
  2028.         pmtl[xside] += valueP;
  2029. #if ttblsz
  2030.       if (hashflag)
  2031.         UpdateHashbd (xside, *tempb, -1, t);
  2032. #endif /* ttblsz */
  2033.       Mvboard[t]--;
  2034.     }
  2035.       if (node->flags & epmask)
  2036.     EnPassant (xside, f, t, 2);
  2037.       else
  2038. #if ttblsz
  2039.       if (hashflag)
  2040.     UpdateHashbd (side, board[f], f, t);
  2041. #endif /* ttblsz */
  2042.       Mvboard[f]--;
  2043.     }
  2044. }
  2045.  
  2046.  
  2047. #if ttblsz
  2048. void
  2049. UpdateHashbd (side, piece, f, t)
  2050.      short int side;
  2051.      short int piece;
  2052.      short int f;
  2053.      short int t;
  2054.  
  2055. /*
  2056.   hashbd contains a 32 bit "signature" of the board position. hashkey
  2057.   contains a 16 bit code used to address the hash table. When a move is
  2058.   made, XOR'ing the hashcode of moved piece on the from and to squares with
  2059.   the hashbd and hashkey values keeps things current.
  2060. */
  2061.  
  2062. {
  2063.   if (f >= 0)
  2064.     {
  2065.       hashbd ^= hashcode[side][piece][f].bd;
  2066.       hashkey ^= hashcode[side][piece][f].key;
  2067.     }
  2068.   if (t >= 0)
  2069.     {
  2070.       hashbd ^= hashcode[side][piece][t].bd;
  2071.       hashkey ^= hashcode[side][piece][t].key;
  2072.     }
  2073. }
  2074.  
  2075. #endif /* ttblsz */
  2076.  
  2077. void
  2078. InitializeStats ()
  2079. /*
  2080.   Scan thru the board seeing what's on each square. If a piece is found,
  2081.   update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  2082.   determine the material for each side and set the hashkey and hashbd
  2083.   variables to represent the current board position. Array
  2084.   PieceList[side][indx] contains the location of all the pieces of either
  2085.   side. Array Pindex[sq] contains the indx into PieceList for a given
  2086.   square.
  2087. */
  2088. {
  2089.   register short i, sq;
  2090.   epsquare = -1;
  2091.   for (i = 0; i < 8; i++)
  2092.     PawnCnt[white][i] = PawnCnt[black][i] = 0;
  2093.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  2094.   PieceCnt[white] = PieceCnt[black] = 0;
  2095. #if ttblsz
  2096.   hashbd = hashkey = 0;
  2097. #endif /* ttblsz */
  2098.   for (sq = 0; sq < 64; sq++)
  2099.     if (color[sq] != neutral)
  2100.       {
  2101.     mtl[color[sq]] += value[board[sq]];
  2102.     if (board[sq] == pawn)
  2103.       {
  2104.         pmtl[color[sq]] += valueP;
  2105.         ++PawnCnt[color[sq]][column (sq)];
  2106.       }
  2107.     if (board[sq] == king)
  2108.       Pindex[sq] = 0;
  2109.     else
  2110.       Pindex[sq] = ++PieceCnt[color[sq]];
  2111.     PieceList[color[sq]][Pindex[sq]] = sq;
  2112. #if ttblsz
  2113.     hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  2114.     hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  2115. #endif /* ttblsz */
  2116.       }
  2117. }
  2118.  
  2119.  
  2120. int
  2121. SqAtakd (sq, side)
  2122.      short int sq;
  2123.      short int side;
  2124.  
  2125. /*
  2126.   See if any piece with color 'side' ataks sq.  First check pawns then Queen,
  2127.   Bishop, Rook and King and last Knight.
  2128. */
  2129.  
  2130. {
  2131.   register short u;
  2132.   register unsigned char *ppos, *pdir;
  2133.   short xside;
  2134.  
  2135.   xside = otherside[side];
  2136.   pdir = nextdir[ptype[xside][pawn]][sq];
  2137.   u = pdir[sq];        /* follow captures thread */
  2138.   if (u != sq)
  2139.     {
  2140.       if (board[u] == pawn && color[u] == side)
  2141.     return (true);
  2142.       u = pdir[u];
  2143.       if (u != sq && board[u] == pawn && color[u] == side)
  2144.     return (true);
  2145.     }
  2146.   /* king capture */
  2147.   if (distance (sq, PieceList[side][0]) == 1)
  2148.     return (true);
  2149.   /* try a queen bishop capture */
  2150.   ppos = nextpos[bishop][sq];
  2151.   pdir = nextdir[bishop][sq];
  2152.   u = ppos[sq];
  2153.   do
  2154.     {
  2155.       if (color[u] == neutral)
  2156.     u = ppos[u];
  2157.       else
  2158.     {
  2159.       if (color[u] == side &&
  2160.           (board[u] == queen || board[u] == bishop))
  2161.         return (true);
  2162.       u = pdir[u];
  2163.     }
  2164.   } while (u != sq);
  2165.   /* try a queen rook capture */
  2166.   ppos = nextpos[rook][sq];
  2167.   pdir = nextdir[rook][sq];
  2168.   u = ppos[sq];
  2169.   do
  2170.     {
  2171.       if (color[u] == neutral)
  2172.     u = ppos[u];
  2173.       else
  2174.     {
  2175.       if (color[u] == side &&
  2176.           (board[u] == queen || board[u] == rook))
  2177.         return (true);
  2178.       u = pdir[u];
  2179.     }
  2180.   } while (u != sq);
  2181.   /* try a knight capture */
  2182.   ppos = nextpos[knight][sq];
  2183.   pdir = nextdir[knight][sq];
  2184.   u = ppos[sq];
  2185.   do
  2186.     {
  2187.       if (color[u] == side && board[u] == knight)
  2188.     return (true);
  2189.       u = pdir[u];
  2190.   } while (u != sq);
  2191.   return (false);
  2192. }
  2193.  
  2194. inline void
  2195. ataks (side, a)
  2196.      short int side;
  2197.      short int *a;
  2198.  
  2199. /*
  2200.   Fill array atak[][] with info about ataks to a square.  Bits 8-15 are set
  2201.   if the piece (king..pawn) ataks the square.  Bits 0-7 contain a count of
  2202.   total ataks to the square.
  2203. */
  2204.  
  2205. {
  2206.   register short u, c, sq;
  2207.   register unsigned char *ppos, *pdir;
  2208.   short i, piece, *PL;
  2209.  
  2210. #ifdef NOMEMSET
  2211.   for (u = 64; u; a[--u] = 0) ;
  2212. #else
  2213.   memset ((char *) a, 0, 64 * sizeof (a[0]));
  2214. #endif /* NOMEMSET */
  2215.   PL = PieceList[side];
  2216.   for (i = PieceCnt[side]; i >= 0; i--)
  2217.     {
  2218.       sq = PL[i];
  2219.       piece = board[sq];
  2220.       c = control[piece];
  2221.       if (sweep[piece])
  2222.     {
  2223.       ppos = nextpos[piece][sq];
  2224.       pdir = nextdir[piece][sq];
  2225.       u = ppos[sq];
  2226.       do
  2227.         {
  2228.           a[u] = ++a[u] | c;
  2229.           u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2230.       } while (u != sq);
  2231.     }
  2232.       else
  2233.     {
  2234.       pdir = nextdir[ptype[side][piece]][sq];
  2235.       u = pdir[sq];    /* follow captures thread for pawns */
  2236.       do
  2237.         {
  2238.           a[u] = ++a[u] | c;
  2239.           u = pdir[u];
  2240.       } while (u != sq);
  2241.     }
  2242.     }
  2243. }
  2244.  
  2245. /* ............    POSITIONAL EVALUATION ROUTINES    ............ */
  2246.  
  2247. int
  2248. evaluate (side, xside, ply, alpha, beta)
  2249.      short int side;
  2250.      short int xside;
  2251.      short int ply;
  2252.      short int alpha;
  2253.      short int beta;
  2254. /*
  2255.   Compute an estimate of the score by adding the positional score from the
  2256.   previous ply to the material difference. If this score falls inside a
  2257.   window which is 180 points wider than the alpha-beta window (or within a
  2258.   50 point window during quiescence search) call ScorePosition() to
  2259.   determine a score, otherwise return the estimated score. If one side has
  2260.   only a king and the other either has no pawns or no pieces then the
  2261.   function ScoreLoneKing() is called.
  2262. */
  2263.  
  2264. {
  2265.   register short evflag;
  2266.   short s;
  2267.  
  2268.   s = -Pscore[ply - 1] + mtl[side] - mtl[xside] - INCscore;
  2269.   hung[white] = hung[black] = 0;
  2270.  
  2271.   if (slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
  2272.      (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0))))
  2273.     evflag = false;
  2274.   else
  2275.     evflag =
  2276.         (ply == 1 || ply < Sdepth ||
  2277.         ((ply == Sdepth + 1 || ply == Sdepth + 2) &&
  2278.         (s > alpha - xwndw && s < beta + xwndw)) ||
  2279.         (ply > Sdepth + 2 && s >= alpha - 25 && s <= beta + 25));
  2280.  
  2281.   if (evflag)
  2282.     {
  2283.       EvalNodes++;
  2284.       ataks (side, atak[side]);
  2285.       if (atak[side][PieceList[xside][0]] > 0)
  2286.             return (10001 - ply);
  2287.       ataks (xside, atak[xside]);
  2288.       InChk = (atak[xside][PieceList[side][0]] > 0);
  2289.       ScorePosition (side, &s);
  2290.     }
  2291.   else
  2292.     {
  2293.       if (SqAtakd (PieceList[xside][0], side))
  2294.             return (10001 - ply);
  2295.       InChk = SqAtakd (PieceList[side][0], xside);
  2296.       if (slk)
  2297.             ScoreLoneKing (side, &s);
  2298.     }
  2299.  
  2300.   Pscore[ply] = s - mtl[side] + mtl[xside];
  2301.   if (InChk)
  2302.     ChkFlag[ply - 1] = Pindex[TOsquare];
  2303.   else
  2304.     ChkFlag[ply - 1] = 0;
  2305.   return (s);
  2306. }
  2307.  
  2308. void
  2309. ScorePosition (side, score)
  2310.      short int side;
  2311.      short int *score;
  2312. /*
  2313.   Perform normal static evaluation of board position. A score is generated
  2314.   for each piece and these are summed to get a score for each side.
  2315. */
  2316.  
  2317. {
  2318.   register short sq, s, i, xside;
  2319.   short pscore[3];
  2320.  
  2321.   wking = PieceList[white][0];
  2322.   bking = PieceList[black][0];
  2323.   UpdateWeights ();
  2324.   xside = otherside[side];
  2325.   pscore[white] = pscore[black] = 0;
  2326.  
  2327.   for (c1 = white; c1 <= black; c1++)
  2328.     {
  2329.       c2 = otherside[c1];
  2330.       if (c1 == white)
  2331.             EnemyKing = bking;
  2332.       else
  2333.             EnemyKing = wking;
  2334.       atk1 = atak[c1];
  2335.       atk2 = atak[c2];
  2336.       PC1 = PawnCnt[c1];
  2337.       PC2 = PawnCnt[c2];
  2338.       for (i = 0; i <= PieceCnt[c1]; i++)
  2339.     {
  2340.       sq = PieceList[c1][i];
  2341.       s = SqValue (sq, side);
  2342.       pscore[c1] += s;
  2343.       svalue[sq] = s;
  2344.     }
  2345.     }
  2346.   if (hung[side] > 1)
  2347.     pscore[side] += HUNGX;
  2348.   if (hung[xside] > 1)
  2349.     pscore[xside] += HUNGX;
  2350.  
  2351.   *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
  2352.   if (dither)
  2353.     *score += rand () % dither;
  2354.  
  2355.   if (*score > 0 && pmtl[side] == 0)
  2356.     if (emtl[side] < valueR)
  2357.       *score = 0;
  2358.     else if (*score < valueR)
  2359.       *score /= 2;
  2360.   if (*score < 0 && pmtl[xside] == 0)
  2361.     if (emtl[xside] < valueR)
  2362.       *score = 0;
  2363.     else if (-*score < valueR)
  2364.       *score /= 2;
  2365.  
  2366.   if (mtl[xside] == valueK && emtl[side] > valueB)
  2367.     *score += 200;
  2368.   if (mtl[side] == valueK && emtl[xside] > valueB)
  2369.     *score -= 200;
  2370. }
  2371.  
  2372. void
  2373. ScoreLoneKing (side, score)
  2374.      short int side;
  2375.      short int *score;
  2376.  
  2377. /*
  2378.   Static evaluation when loser has only a king and winner has no pawns or no
  2379.   pieces.
  2380. */
  2381.  
  2382. {
  2383.   register short winner, loser, king1, king2, s, i;
  2384.  
  2385.   UpdateWeights ();
  2386.   if (mtl[white] > mtl[black])
  2387.     winner = white;
  2388.   else
  2389.     winner = black;
  2390.   loser = otherside[winner];
  2391.   king1 = PieceList[winner][0];
  2392.   king2 = PieceList[loser][0];
  2393.  
  2394.   s = 0;
  2395.  
  2396.   if (pmtl[winner] > 0)
  2397.     for (i = 1; i <= PieceCnt[winner]; i++)
  2398.       s += ScoreKPK (side, winner, loser, king1, king2, PieceList[winner][i]);
  2399.  
  2400.   else if (emtl[winner] == valueB + valueN)
  2401.     s = ScoreKBNK (winner, king1, king2);
  2402.  
  2403.   else if (emtl[winner] > valueB)
  2404.     s = 500 + emtl[winner] - DyingKing[king2] - 2 * distance (king1, king2);
  2405.  
  2406.   if (side == winner)
  2407.     *score = s;
  2408.   else
  2409.     *score = -s;
  2410. }
  2411.  
  2412.  
  2413. int
  2414. ScoreKPK (side, winner, loser, king1, king2, sq)
  2415.      short int side;
  2416.      short int winner;
  2417.      short int loser;
  2418.      short int king1;
  2419.      short int king2;
  2420.      short int sq;
  2421.  
  2422. /*
  2423.   Score King and Pawns versus King endings.
  2424. */
  2425.  
  2426. {
  2427.   register short s, r;
  2428.  
  2429.   if (PieceCnt[winner] == 1)
  2430.     s = 50;
  2431.   else
  2432.     s = 120;
  2433.   if (winner == white)
  2434.     {
  2435.       if (side == loser)
  2436.     r = row (sq) - 1;
  2437.       else
  2438.     r = row (sq);
  2439.       if (row (king2) >= r && distance (sq, king2) < 8 - r)
  2440.     s += 10 * row (sq);
  2441.       else
  2442.     s = 500 + 50 * row (sq);
  2443.       if (row (sq) < 6)
  2444.     sq += 16;
  2445.       else
  2446.     sq += 8;
  2447.     }
  2448.   else
  2449.     {
  2450.       if (side == loser)
  2451.     r = row (sq) + 1;
  2452.       else
  2453.     r = row (sq);
  2454.       if (row (king2) <= r && distance (sq, king2) < r + 1)
  2455.     s += 10 * (7 - row (sq));
  2456.       else
  2457.     s = 500 + 50 * (7 - row (sq));
  2458.       if (row (sq) > 1)
  2459.     sq -= 16;
  2460.       else
  2461.     sq -= 8;
  2462.     }
  2463.   s += 8 * (taxicab (king2, sq) - taxicab (king1, sq));
  2464.   return (s);
  2465. }
  2466.  
  2467.  
  2468. int
  2469. ScoreKBNK (winner, king1, king2)
  2470.      short int winner;
  2471.      short int king1;
  2472.      short int king2;
  2473.  
  2474.  
  2475. /*
  2476.   Score King+Bishop+Knight versus King endings.
  2477.   This doesn't work all that well but it's better than nothing.
  2478. */
  2479.  
  2480. {
  2481.   register short s;
  2482.  
  2483.   s = emtl[winner] - 300;
  2484.   if (KBNKsq == 0)
  2485.     s += KBNK[king2];
  2486.   else
  2487.     s += KBNK[locn (row (king2), 7 - column (king2))];
  2488.   s -= taxicab (king1, king2);
  2489.   s -= distance (PieceList[winner][1], king2);
  2490.   s -= distance (PieceList[winner][2], king2);
  2491.   return (s);
  2492. }
  2493.  
  2494.  
  2495. inline void
  2496. BRscan (sq, s, mob)
  2497.      short int sq;
  2498.      short int *s;
  2499.      short int *mob;
  2500.  
  2501. /*
  2502.   Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
  2503.   hung[] array if a pin is found.
  2504. */
  2505. {
  2506.   register short u, piece, pin;
  2507.   register unsigned char *ppos, *pdir;
  2508.   short *Kf;
  2509.  
  2510.   Kf = Kfield[c1];
  2511.   *mob = 0;
  2512.   piece = board[sq];
  2513.   ppos = nextpos[piece][sq];
  2514.   pdir = nextdir[piece][sq];
  2515.   u = ppos[sq];
  2516.   pin = -1;            /* start new direction */
  2517.   do
  2518.     {
  2519.       *s += Kf[u];
  2520.       if (color[u] == neutral)
  2521.     {
  2522.       (*mob)++;
  2523.       if (ppos[u] == pdir[u])
  2524.         pin = -1;        /* oops new direction */
  2525.       u = ppos[u];
  2526.     }
  2527.       else if (pin < 0)
  2528.     {
  2529.       if (board[u] == pawn || board[u] == king)
  2530.         u = pdir[u];
  2531.       else
  2532.         {
  2533.           if (ppos[u] != pdir[u])
  2534.         pin = u;    /* not on the edge and on to find a pin */
  2535.           u = ppos[u];
  2536.         }
  2537.     }
  2538.       else
  2539.     {
  2540.       if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
  2541.         {
  2542.           if (color[pin] == c2)
  2543.         {
  2544.           *s += PINVAL;
  2545.           if (atk2[pin] == 0 ||
  2546.               atk1[pin] > control[board[pin]] + 1)
  2547.             ++hung[c2];
  2548.         }
  2549.           else
  2550.         *s += XRAY;
  2551.         }
  2552.       pin = -1;        /* new direction */
  2553.       u = pdir[u];
  2554.     }
  2555.   } while (u != sq);
  2556. }
  2557.  
  2558. int
  2559. SqValue (sq, side)
  2560.      short int sq;
  2561.      short int side;
  2562.  
  2563. /*
  2564.   Calculate the positional value for the piece on 'sq'.
  2565. */
  2566.  
  2567. {
  2568.   register short j, fyle, rank;
  2569.   short s, piece, a1, a2, in_square, r, mob, e, c;
  2570.  
  2571.   piece = board[sq];
  2572.   a1 = (atk1[sq] & 0x4FFF);
  2573.   a2 = (atk2[sq] & 0x4FFF);
  2574.   rank = row (sq);
  2575.   fyle = column (sq);
  2576.   s = 0;
  2577.   if (piece == pawn && c1 == white)
  2578.     {
  2579.       s = Mwpawn[sq];
  2580.       if (sq == 11 || sq == 12)
  2581.     if (color[sq + 8] != neutral)
  2582.       s += PEDRNK2B;
  2583.       if ((fyle == 0 || PC1[fyle - 1] == 0) &&
  2584.       (fyle == 7 || PC1[fyle + 1] == 0))
  2585.     s += ISOLANI[fyle];
  2586.       else if (PC1[fyle] > 1)
  2587.     s += PDOUBLED;
  2588.       if (a1 < ctlP && atk1[sq + 8] < ctlP)
  2589.     {
  2590.       s += BACKWARD[a2 & 0xFF];
  2591.       if (PC2[fyle] == 0)
  2592.         s += PWEAKH;
  2593.       if (color[sq + 8] != neutral)
  2594.         s += PBLOK;
  2595.     }
  2596.       if (PC2[fyle] == 0)
  2597.     {
  2598.       if (side == black)
  2599.         r = rank - 1;
  2600.       else
  2601.         r = rank;
  2602.       in_square = (row (bking) >= r && distance (sq, bking) < 8 - r);
  2603.       if (a2 == 0 || side == white)
  2604.         e = 0;
  2605.       else
  2606.         e = 1;
  2607.       for (j = sq + 8; j < 64; j += 8)
  2608.         if (atk2[j] >= ctlP)
  2609.           {
  2610.         e = 2;
  2611.         break;
  2612.           }
  2613.         else if (atk2[j] > 0 || color[j] != neutral)
  2614.           e = 1;
  2615.       if (e == 2)
  2616.         s += (stage * PassedPawn3[rank]) / 10;
  2617.       else if (in_square || e == 1)
  2618.         s += (stage * PassedPawn2[rank]) / 10;
  2619.       else if (emtl[black] > 0)
  2620.         s += (stage * PassedPawn1[rank]) / 10;
  2621.       else
  2622.         s += PassedPawn0[rank];
  2623.     }
  2624.     }
  2625.   else if (piece == pawn && c1 == black)
  2626.     {
  2627.       s = Mbpawn[sq];
  2628.       if (sq == 51 || sq == 52)
  2629.     if (color[sq - 8] != neutral)
  2630.       s += PEDRNK2B;
  2631.       if ((fyle == 0 || PC1[fyle - 1] == 0) &&
  2632.       (fyle == 7 || PC1[fyle + 1] == 0))
  2633.     s += ISOLANI[fyle];
  2634.       else if (PC1[fyle] > 1)
  2635.     s += PDOUBLED;
  2636.       if (a1 < ctlP && atk1[sq - 8] < ctlP)
  2637.     {
  2638.       s += BACKWARD[a2 & 0xFF];
  2639.       if (PC2[fyle] == 0)
  2640.         s += PWEAKH;
  2641.       if (color[sq - 8] != neutral)
  2642.         s += PBLOK;
  2643.     }
  2644.       if (PC2[fyle] == 0)
  2645.     {
  2646.       if (side == white)
  2647.         r = rank + 1;
  2648.       else
  2649.         r = rank;
  2650.       in_square = (row (wking) <= r && distance (sq, wking) < r + 1);
  2651.       if (a2 == 0 || side == black)
  2652.         e = 0;
  2653.       else
  2654.         e = 1;
  2655.       for (j = sq - 8; j >= 0; j -= 8)
  2656.         if (atk2[j] >= ctlP)
  2657.           {
  2658.         e = 2;
  2659.         break;
  2660.           }
  2661.         else if (atk2[j] > 0 || color[j] != neutral)
  2662.           e = 1;
  2663.       if (e == 2)
  2664.         s += (stage * PassedPawn3[7 - rank]) / 10;
  2665.       else if (in_square || e == 1)
  2666.         s += (stage * PassedPawn2[7 - rank]) / 10;
  2667.       else if (emtl[white] > 0)
  2668.         s += (stage * PassedPawn1[7 - rank]) / 10;
  2669.       else
  2670.         s += PassedPawn0[7 - rank];
  2671.     }
  2672.     }
  2673.   else if (piece == knight)
  2674.     {
  2675.       s = Mknight[c1][sq];
  2676.     }
  2677.   else if (piece == bishop)
  2678.     {
  2679.       s = Mbishop[c1][sq];
  2680.       BRscan (sq, &s, &mob);
  2681.       s += BMBLTY[mob];
  2682.     }
  2683.   else if (piece == rook)
  2684.     {
  2685.       s += RookBonus;
  2686.       BRscan (sq, &s, &mob);
  2687.       s += RMBLTY[mob];
  2688.       if (PC1[fyle] == 0)
  2689.     s += RHOPN;
  2690.       if (PC2[fyle] == 0)
  2691.     s += RHOPNX;
  2692.       if (rank == rank7[c1] && pmtl[c2] > 100)
  2693.     s += 10;
  2694.       if (stage > 2)
  2695.     s += 14 - taxicab (sq, EnemyKing);
  2696.     }
  2697.   else if (piece == queen)
  2698.     {
  2699.       if (stage > 2)
  2700.     s += 14 - taxicab (sq, EnemyKing);
  2701.       if (distance (sq, EnemyKing) < 3)
  2702.     s += 12;
  2703.     }
  2704.   else if (piece == king)
  2705.     {
  2706.       s = Mking[c1][sq];
  2707.       if (KSFTY > 0)
  2708.     if (Developed[c2] || stage > 0)
  2709.       KingScan (sq, &s);
  2710.       if (castld[c1])
  2711.     s += KCASTLD;
  2712.       else if (Mvboard[kingP[c1]])
  2713.     s += KMOVD;
  2714.  
  2715.       if (PC1[fyle] == 0)
  2716.     s += KHOPN;
  2717.       if (PC2[fyle] == 0)
  2718.     s += KHOPNX;
  2719.       if (fyle == 1 || fyle == 2 || fyle == 3 || fyle == 7)
  2720.     {
  2721.       if (PC1[fyle - 1] == 0)
  2722.         s += KHOPN;
  2723.       if (PC2[fyle - 1] == 0)
  2724.         s += KHOPNX;
  2725.     }
  2726.       if (fyle == 4 || fyle == 5 || fyle == 6 || fyle == 0)
  2727.     {
  2728.       if (PC1[fyle + 1] == 0)
  2729.         s += KHOPN;
  2730.       if (PC2[fyle + 1] == 0)
  2731.         s += KHOPNX;
  2732.     }
  2733.       if (fyle == 2)
  2734.     {
  2735.       if (PC1[0] == 0)
  2736.         s += KHOPN;
  2737.       if (PC2[0] == 0)
  2738.         s += KHOPNX;
  2739.     }
  2740.       if (fyle == 5)
  2741.     {
  2742.       if (PC1[7] == 0)
  2743.         s += KHOPN;
  2744.       if (PC2[7] == 0)
  2745.         s += KHOPNX;
  2746.     }
  2747.     }
  2748.   if (a2 > 0)
  2749.     {
  2750.       c = (control[piece] & 0x4FFF);
  2751.       if (a1 == 0 || a2 > c + 1)
  2752.     {
  2753.       s += HUNGP;
  2754.       ++hung[c1];
  2755.       if (piece != king && trapped (sq, piece))
  2756.         ++hung[c1];
  2757.     }
  2758.       else if (piece != pawn || a2 > a1)
  2759.     if (a2 >= c || a1 < ctlP)
  2760.       s += ATAKD;
  2761.     }
  2762.   return (s);
  2763. }
  2764.  
  2765. void
  2766. KingScan (sq, s)
  2767.      short int sq;
  2768.      short int *s;
  2769.  
  2770. /*
  2771.   Assign penalties if king can be threatened by checks, if squares
  2772.   near the king are controlled by the enemy (especially the queen),
  2773.   or if there are no pawns near the king.
  2774.   The following must be true:
  2775.   board[sq] == king
  2776.   c1 == color[sq]
  2777.   c2 == otherside[c1]
  2778. */
  2779.  
  2780. #define ScoreThreat \
  2781. if (color[u] != c2)\
  2782.   if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\
  2783.   else *s -= 3
  2784.  
  2785. {
  2786.   register short u;
  2787.   register unsigned char *ppos, *pdir;
  2788.   register short cnt, ok;
  2789.  
  2790.   cnt = 0;
  2791.   if (HasBishop[c2] || HasQueen[c2])
  2792.     {
  2793.       ppos = nextpos[bishop][sq];
  2794.       pdir = nextdir[bishop][sq];
  2795.       u = ppos[sq];
  2796.       do
  2797.     {
  2798.       if (atk2[u] & ctlBQ)
  2799.         ScoreThreat;
  2800.       u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2801.       } while (u != sq);
  2802.     }
  2803.   if (HasRook[c2] || HasQueen[c2])
  2804.     {
  2805.       ppos = nextpos[rook][sq];
  2806.       pdir = nextdir[rook][sq];
  2807.       u = ppos[sq];
  2808.       do
  2809.     {
  2810.       if (atk2[u] & ctlRQ)
  2811.         ScoreThreat;
  2812.       u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2813.       } while (u != sq);
  2814.     }
  2815.   if (HasKnight[c2])
  2816.     {
  2817.       pdir = nextdir[knight][sq];
  2818.       u = pdir[sq];
  2819.       do
  2820.     {
  2821.       if (atk2[u] & ctlNN)
  2822.         ScoreThreat;
  2823.       u = pdir[u];
  2824.       } while (u != sq);
  2825.     }
  2826.   *s += (KSFTY * KTHRT[cnt]) / 16;
  2827.  
  2828.   cnt = 0;
  2829.   ok = false;
  2830.   pdir = nextpos[king][sq];
  2831.   u = pdir[sq];
  2832.   do
  2833.     {
  2834.       if (board[u] == pawn)
  2835.     ok = true;
  2836.       if (atk2[u] > atk1[u])
  2837.     {
  2838.       ++cnt;
  2839.       if (atk2[u] & ctlQ)
  2840.         if (atk2[u] > ctlQ + 1 && atk1[u] < ctlQ)
  2841.           *s -= 4 * KSFTY;
  2842.     }
  2843.       u = pdir[u];
  2844.   } while (u != sq);
  2845.   if (!ok)
  2846.     *s -= KSFTY;
  2847.   if (cnt > 1)
  2848.     *s -= KSFTY;
  2849. }
  2850.  
  2851.  
  2852. int
  2853. trapped (sq, piece)
  2854.      short int sq;
  2855.      short int piece;
  2856.  
  2857. /*
  2858.   See if the attacked piece has unattacked squares to move to.
  2859.   The following must be true:
  2860.   piece == board[sq]
  2861.   c1 == color[sq]
  2862.   c2 == otherside[c1]
  2863. */
  2864.  
  2865. {
  2866.   register short u;
  2867.   register unsigned char *ppos, *pdir;
  2868.  
  2869.   ppos = nextpos[ptype[c1][piece]][sq];
  2870.   pdir = nextdir[ptype[c1][piece]][sq];
  2871.   if (piece == pawn)
  2872.     {
  2873.       u = ppos[sq];    /* follow no captures thread */
  2874.       if (color[u] == neutral)
  2875.     {
  2876.       if (atk1[u] >= atk2[u])
  2877.         return (false);
  2878.       if (atk2[u] < ctlP)
  2879.         {
  2880.           u = ppos[u];
  2881.           if (color[u] == neutral && atk1[u] >= atk2[u])
  2882.         return (false);
  2883.         }
  2884.     }
  2885.       u = pdir[sq];    /* follow captures thread */
  2886.       if (color[u] == c2)
  2887.     return (false);
  2888.       u = pdir[u];
  2889.       if (color[u] == c2)
  2890.     return (false);
  2891.     }
  2892.   else
  2893.     {
  2894.       u = ppos[sq];
  2895.       do
  2896.     {
  2897.       if (color[u] != c1)
  2898.         if (atk2[u] == 0 || board[u] >= piece)
  2899.           return (false);
  2900.       u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2901.       } while (u != sq);
  2902.     }
  2903.   return (true);
  2904. }
  2905.  
  2906.  
  2907. inline void
  2908. BlendBoard (a, b, c)
  2909.      const short int *a;
  2910.      const short int *b;
  2911.      short int *c;
  2912. {
  2913.   register int sq;
  2914.  
  2915.   for (sq = 0; sq < 64; sq++)
  2916.     c[sq] = (a[sq] * (10 - stage) + b[sq] * stage) / 10;
  2917. }
  2918.  
  2919.  
  2920. inline void
  2921. CopyBoard (a, b)
  2922.      const short int *a;
  2923.      short int *b;
  2924. {
  2925.   register int sq;
  2926.  
  2927.   for (sq = 0; sq < 64; sq++)
  2928.     b[sq] = a[sq];
  2929. }
  2930.  
  2931. void
  2932. ExaminePosition ()
  2933.  
  2934. /*
  2935.   This is done one time before the search is started. Set up arrays
  2936.   Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the
  2937.   SqValue() function to determine the positional value of each piece.
  2938. */
  2939.  
  2940. {
  2941.   register short i, sq;
  2942.   short wpadv, bpadv, wstrong, bstrong, z, side, pp, j, k, val, Pd, fyle, rank;
  2943.  
  2944.   wking = PieceList[white][0];
  2945.   bking = PieceList[black][0];
  2946.   ataks (white, atak[white]);
  2947.   ataks (black, atak[black]);
  2948.   Zwmtl = Zbmtl = 0;
  2949.   UpdateWeights ();
  2950.   HasPawn[white] = HasPawn[black] = 0;
  2951.   HasKnight[white] = HasKnight[black] = 0;
  2952.   HasBishop[white] = HasBishop[black] = 0;
  2953.   HasRook[white] = HasRook[black] = 0;
  2954.   HasQueen[white] = HasQueen[black] = 0;
  2955.   for (side = white; side <= black; side++)
  2956.     for (i = 0; i <= PieceCnt[side]; i++)
  2957.       switch (board[PieceList[side][i]])
  2958.     {
  2959.     case pawn:
  2960.       ++HasPawn[side];
  2961.       break;
  2962.     case knight:
  2963.       ++HasKnight[side];
  2964.       break;
  2965.     case bishop:
  2966.       ++HasBishop[side];
  2967.       break;
  2968.     case rook:
  2969.       ++HasRook[side];
  2970.       break;
  2971.     case queen:
  2972.       ++HasQueen[side];
  2973.       break;
  2974.     }
  2975.   if (!Developed[white])
  2976.     Developed[white] = (board[1] != knight && board[2] != bishop &&
  2977.             board[5] != bishop && board[6] != knight);
  2978.   if (!Developed[black])
  2979.     Developed[black] = (board[57] != knight && board[58] != bishop &&
  2980.             board[61] != bishop && board[62] != knight);
  2981.   if (!PawnStorm && stage < 5)
  2982.     PawnStorm = ((column (wking) < 3 && column (bking) > 4) ||
  2983.          (column (wking) > 4 && column (bking) < 3));
  2984.  
  2985.   CopyBoard (pknight, Mknight[white]);
  2986.   CopyBoard (pknight, Mknight[black]);
  2987.   CopyBoard (pbishop, Mbishop[white]);
  2988.   CopyBoard (pbishop, Mbishop[black]);
  2989.   BlendBoard (KingOpening, KingEnding, Mking[white]);
  2990.   BlendBoard (KingOpening, KingEnding, Mking[black]);
  2991.  
  2992.   for (sq = 0; sq < 64; sq++)
  2993.     {
  2994.       fyle = column (sq);
  2995.       rank = row (sq);
  2996.       wstrong = bstrong = true;
  2997.       for (i = sq; i < 64; i += 8)
  2998.     if (atak[black][i] >= ctlP)
  2999.       {
  3000.         wstrong = false;
  3001.         break;
  3002.       }
  3003.       for (i = sq; i >= 0; i -= 8)
  3004.     if (atak[white][i] >= ctlP)
  3005.       {
  3006.         bstrong = false;
  3007.         break;
  3008.       }
  3009.       wpadv = bpadv = PADVNCM;
  3010.       if ((fyle == 0 || PawnCnt[white][fyle - 1] == 0) &&
  3011.       (fyle == 7 || PawnCnt[white][fyle + 1] == 0))
  3012.     wpadv = PADVNCI;
  3013.       if ((fyle == 0 || PawnCnt[black][fyle - 1] == 0) &&
  3014.       (fyle == 7 || PawnCnt[black][fyle + 1] == 0))
  3015.     bpadv = PADVNCI;
  3016.       Mwpawn[sq] = (wpadv * PawnAdvance[sq]) / 10;
  3017.       Mbpawn[sq] = (bpadv * PawnAdvance[63 - sq]) / 10;
  3018.       Mwpawn[sq] += PawnBonus;
  3019.       Mbpawn[sq] += PawnBonus;
  3020.       if (Mvboard[kingP[white]])
  3021.     {
  3022.       if ((fyle < 3 || fyle > 4) && distance (sq, wking) < 3)
  3023.         Mwpawn[sq] += PAWNSHIELD;
  3024.     }
  3025.       else if (rank < 3 && (fyle < 2 || fyle > 5))
  3026.     Mwpawn[sq] += PAWNSHIELD / 2;
  3027.       if (Mvboard[kingP[black]])
  3028.     {
  3029.       if ((fyle < 3 || fyle > 4) && distance (sq, bking) < 3)
  3030.         Mbpawn[sq] += PAWNSHIELD;
  3031.     }
  3032.       else if (rank > 4 && (fyle < 2 || fyle > 5))
  3033.     Mbpawn[sq] += PAWNSHIELD / 2;
  3034.       if (PawnStorm)
  3035.     {
  3036.       if ((column (wking) < 4 && fyle > 4) ||
  3037.           (column (wking) > 3 && fyle < 3))
  3038.         Mwpawn[sq] += 3 * rank - 21;
  3039.       if ((column (bking) < 4 && fyle > 4) ||
  3040.           (column (bking) > 3 && fyle < 3))
  3041.         Mbpawn[sq] -= 3 * rank;
  3042.     }
  3043.       Mknight[white][sq] += 5 - distance (sq, bking);
  3044.       Mknight[white][sq] += 5 - distance (sq, wking);
  3045.       Mknight[black][sq] += 5 - distance (sq, wking);
  3046.       Mknight[black][sq] += 5 - distance (sq, bking);
  3047.       Mbishop[white][sq] += BishopBonus;
  3048.       Mbishop[black][sq] += BishopBonus;
  3049.       for (i = 0; i <= PieceCnt[black]; i++)
  3050.     if (distance (sq, PieceList[black][i]) < 3)
  3051.       Mknight[white][sq] += KNIGHTPOST;
  3052.       for (i = 0; i <= PieceCnt[white]; i++)
  3053.     if (distance (sq, PieceList[white][i]) < 3)
  3054.       Mknight[black][sq] += KNIGHTPOST;
  3055.       if (wstrong)
  3056.     Mknight[white][sq] += KNIGHTSTRONG;
  3057.       if (bstrong)
  3058.     Mknight[black][sq] += KNIGHTSTRONG;
  3059.       if (wstrong)
  3060.     Mbishop[white][sq] += BISHOPSTRONG;
  3061.       if (bstrong)
  3062.     Mbishop[black][sq] += BISHOPSTRONG;
  3063.  
  3064.       if (HasBishop[white] == 2)
  3065.     Mbishop[white][sq] += 8;
  3066.       if (HasBishop[black] == 2)
  3067.     Mbishop[black][sq] += 8;
  3068.       if (HasKnight[white] == 2)
  3069.     Mknight[white][sq] += 5;
  3070.       if (HasKnight[black] == 2)
  3071.     Mknight[black][sq] += 5;
  3072.  
  3073.       if (board[sq] == bishop)
  3074.     if (rank % 2 == fyle % 2)
  3075.       KBNKsq = 0;
  3076.     else
  3077.       KBNKsq = 7;
  3078.  
  3079.       Kfield[white][sq] = Kfield[black][sq] = 0;
  3080.       if (distance (sq, wking) == 1)
  3081.     Kfield[black][sq] = KATAK;
  3082.       if (distance (sq, bking) == 1)
  3083.     Kfield[white][sq] = KATAK;
  3084.  
  3085.       Pd = 0;
  3086.       for (k = 0; k <= PieceCnt[white]; k++)
  3087.     {
  3088.       i = PieceList[white][k];
  3089.       if (board[i] == pawn)
  3090.         {
  3091.           pp = true;
  3092.           if (row (i) == 6)
  3093.         z = i + 8;
  3094.           else
  3095.         z = i + 16;
  3096.           for (j = i + 8; j < 64; j += 8)
  3097.         if (atak[black][j] > ctlP || board[j] == pawn)
  3098.           {
  3099.             pp = false;
  3100.             break;
  3101.           }
  3102.           if (pp)
  3103.         Pd += 5 * taxicab (sq, z);
  3104.           else
  3105.         Pd += taxicab (sq, z);
  3106.         }
  3107.     }
  3108.       for (k = 0; k <= PieceCnt[black]; k++)
  3109.     {
  3110.       i = PieceList[black][k];
  3111.       if (board[i] == pawn)
  3112.         {
  3113.           pp = true;
  3114.           if (row (i) == 1)
  3115.         z = i - 8;
  3116.           else
  3117.         z = i - 16;
  3118.           for (j = i - 8; j >= 0; j -= 8)
  3119.         if (atak[white][j] > ctlP || board[j] == pawn)
  3120.           {
  3121.             pp = false;
  3122.             break;
  3123.           }
  3124.           if (pp)
  3125.         Pd += 5 * taxicab (sq, z);
  3126.           else
  3127.         Pd += taxicab (sq, z);
  3128.         }
  3129.     }
  3130.       if (Pd != 0)
  3131.     {
  3132.       val = (Pd * stage2) / 10;
  3133.       Mking[white][sq] -= val;
  3134.       Mking[black][sq] -= val;
  3135.     }
  3136.     }
  3137. }
  3138.  
  3139. void
  3140. UpdateWeights ()
  3141.  
  3142. /*
  3143.   If material balance has changed, determine the values for the positional
  3144.   evaluation terms.
  3145. */
  3146.  
  3147. {
  3148.   register short tmtl, s1;
  3149.  
  3150.   if (mtl[white] != Zwmtl || mtl[black] != Zbmtl)
  3151.     {
  3152.       Zwmtl = mtl[white];
  3153.       Zbmtl = mtl[black];
  3154.       emtl[white] = Zwmtl - pmtl[white] - valueK;
  3155.       emtl[black] = Zbmtl - pmtl[black] - valueK;
  3156.       tmtl = emtl[white] + emtl[black];
  3157.       s1 = (tmtl > 6600) ? 0 : ((tmtl < 1400) ? 10 : (6600 - tmtl) / 520);
  3158.       if (s1 != stage)
  3159.     {
  3160.       stage = s1;
  3161.       stage2 = (tmtl > 3600) ? 0 : ((tmtl < 1400) ? 10 : (3600 - tmtl) / 220);
  3162.       PEDRNK2B = -15;    /* centre pawn on 2nd rank & blocked */
  3163.       PBLOK = -4;        /* blocked backward pawn */
  3164.       PDOUBLED = -14;    /* doubled pawn */
  3165.       PWEAKH = -4;        /* weak pawn on half open file */
  3166.       PAWNSHIELD = 10 - stage;    /* pawn near friendly king */
  3167.       PADVNCM = 10;        /* advanced pawn multiplier */
  3168.       PADVNCI = 7;        /* muliplier for isolated pawn */
  3169.       PawnBonus = stage;
  3170.  
  3171.       KNIGHTPOST = (stage + 2) / 3;    /* knight near enemy pieces */
  3172.       KNIGHTSTRONG = (stage + 6) / 2;    /* occupies pawn hole */
  3173.  
  3174.       BISHOPSTRONG = (stage + 6) / 2;    /* occupies pawn hole */
  3175.       BishopBonus = 2 * stage;
  3176.  
  3177.       RHOPN = 10;        /* rook on half open file */
  3178.       RHOPNX = 4;
  3179.       RookBonus = 6 * stage;
  3180.  
  3181.       XRAY = 8;        /* Xray attack on piece */
  3182.       PINVAL = 10;        /* Pin */
  3183.  
  3184.       KHOPN = (3 * stage - 30) / 2;    /* king on half open file */
  3185.       KHOPNX = KHOPN / 2;
  3186.       KCASTLD = 10 - stage;
  3187.       KMOVD = -40 / (stage + 1);    /* king moved before castling */
  3188.       KATAK = (10 - stage) / 2;    /* B,R attacks near enemy king */
  3189.       if (stage < 8)
  3190.         KSFTY = 16 - 2 * stage;
  3191.       else
  3192.         KSFTY = 0;
  3193.  
  3194.       ATAKD = -6;        /* defender > attacker */
  3195.       HUNGP = -8;        /* each hung piece */
  3196.       HUNGX = -12;        /* extra for >1 hung piece */
  3197.     }
  3198.     }
  3199. }
  3200.  
  3201.  
  3202. int
  3203. main ()
  3204. {
  3205.   int ahead = 0;
  3206.   int hash = 0;
  3207.   char *xwin = 0;
  3208.   int l;
  3209.  
  3210.   SetUpThing();
  3211.   SetupMenus();
  3212.   alloc_tables();
  3213.  
  3214.   Level[black] = 1;
  3215.   Level[white] = 1;
  3216.   TCflag[black] = true;
  3217.   TCflag[white] = true;
  3218.   OperatorTime[white] = 0;
  3219.   OperatorTime[black] = 0;
  3220.   Book = NULL;
  3221.   for (l = 0; l < 64; l++)
  3222.     {
  3223.       board[l] = Stboard[l];
  3224.       color[l] = Stcolor[l];
  3225.       Mvboard[l] = 0;
  3226.     }
  3227.   Initialize ();
  3228.   Initialize_dist ();
  3229.   Initialize_moves ();
  3230.  
  3231.   TCmoves[white] = 60;
  3232.   TCmoves[black] = 60;
  3233.   TCminutes[white] = 5;
  3234.   TCminutes[black] = 5;
  3235.   SetTimeControl (white);
  3236.   SetTimeControl (black);
  3237.  
  3238.   if (ahead)
  3239.     seteasy ();
  3240.   if (hash)
  3241.     hashflag = 1;
  3242.   if (xwin)
  3243.     xwndw = atoi (xwin);
  3244.  
  3245. #if ttblsz
  3246. #ifdef HASHFILE
  3247.   hashfile = 0;
  3248. #endif /* HASHFILE */
  3249. #endif  /* ttblsz */
  3250.  
  3251.   loop();
  3252.   
  3253. #if ttblsz
  3254. #ifdef HASHFILE
  3255.   if (hashfile) FSClose(hashfile);
  3256. #endif /* HASHFILE */
  3257. #endif /* ttblsz */
  3258.  
  3259.   ExitChess ();
  3260.   return (0);
  3261. }
  3262.